檢查字串是否有不需要的字元

作為開發人員,你經常發現自己處理的字串不是由你自己的程式碼建立的。

這些通常由第三方庫,外部系統甚至終端使用者提供。驗證不明原因的字串被認為是防禦性程式設計的標誌之一,在大多數情況下,你將要拒絕不符合你期望的字串輸入。

一個相當常見的情況是你只想在輸入字串中允許使用字母數字字元,因此我們將使用它作為示例。在普通的 Java 中,以下兩種方法都有相同的用途:

public static boolean isAlphanumeric(String s) {
    for (char c : s.toCharArray()) {
        if (!Character.isLetterOrDigit(c)) {
            return false;
        }
    }

    return true;
}
public static boolean isAlphanumeric(String s) {
    return s.matches("^[0­-9a­-zA­-Z]*$");
}

第一個版本將字串轉換為字元陣列,然後使用 Character 類’static isLetterOrDigit 方法確定陣列中包含的字元是否為字母數字。這種方法是可預測和可讀的,雖然有點冗長。

第二個版本使用正規表示式來實現相同的目的。它更簡潔,但對於正規表示式知識有限或沒有知識的開發人員可能有些神祕。

Guava 引入了 CharMatcher 類來處理這些型別的情況。我們使用 Guava 進行的字母數字測試如下:

import static com.google.common.base.CharMatcher.javaLetterOrDigit;

/* ... */

public static boolean isAlphanumeric(String s) {
    return javaLetterOrDigit().matchesAllOf(s);
}

方法體只包含一行,但實際上這裡有很多,所以讓我們進一步分解。

如果你看一下 Guava 的 CharMatcher 類的 API,你會發現它實現了 Predicate<Character> 介面。如果你要建立一個自己實現 Predicate<Character> 的類,它可能看起來像這樣:

import com.google.common.base.Predicate;

public class AlphanumericPredicate implements Predicate<Character> {
    @Override
    public boolean apply(Character c) {
        return Character.isLetterOrDigit(c);
    }
}

在 Guava 中,與許多其他程式語言和庫一樣迎合程式設計的功能樣式,謂詞是一種將給定輸入評估為 true 或 false 的構造。在 Guava 的 Predicate<T> 介面中,通過唯一的 boolean apply(T t) 方法的存在就可以看出這一點。CharMatcher 類基於這個概念,將評估一個字元或字元序列,以檢查它們是否符合使用的 CharMatcher 例項所規定的標準。

Guava 目前提供以下預定義字元匹配器:

匹配 描述
any() 匹配任何角色。
none() 不匹配任何字元。
javaDigit() 根據 Java 定義匹配數字。
javaUpperCase() 根據 Java 的定義,匹配任何大寫字元。
javaLowerCase() 根據 Java 的定義,匹配任何小寫字元。
javaLetter() 根據 Java 的定義,匹配任何字母。
javaLetterOrDigit() 根據 Java 的定義,匹配任何字母或數字。
javaIsoControl() 根據 Java 的定義,匹配任何 ISO 控制字元。
ascii() 匹配 ASCII 字符集中的任何字元。
invisible() 根據 Unicode 標準匹配不可見的字元。
digit() 根據 Unicode 規範匹配任何數字。
whitespace() 根據 Unicode 規範匹配任何空白字元。
breakingWhitespace() 根據 unicode 規範匹配任何破碎的空白字元。
singleWidth() 匹配任何單寬字元。

如果你已閱讀上表,你無疑會注意到確定哪些字元屬於某個類別所涉及的定義和規範的數量。到目前為止,Guava 的方法是為 Java 定義的許多字元類別提供 CharMatcher 包裝器,你可以參考 Java 的 Character 類 API 來獲取有關這些類別的更多資訊。另一方面,Guava 嘗試提供許多符合當前 Unicode 規範的 CharMatcher 例項。有關詳細資訊,請參閱 CharMatcher API 文件。

回到我們檢查字串中不需要的字元的示例,以下 CharMatcher 方法提供了檢查給定字串的字元用法是否滿足你的要求所需的功能:

  • boolean matchesNoneOf(CharSequence sequence)
    如果引數字串中的所有字元都與 CharMatcher 例項不匹配,則返回 true。

  • boolean matchesAnyOf(CharSequence sequence)
    如果引數字串中至少有一個字元與 CharMatcher 例項匹配,則返回 true。

  • boolean matchesAllOf(CharSequence sequence)
    如果引數字串中的所有字元都與 CharMatcher 例項匹配,則返回 true。