检查字符串是否有不需要的字符

作为开发人员,你经常发现自己处理的字符串不是由你自己的代码创建的。

这些通常由第三方库,外部系统甚至最终用户提供。验证不明原因的字符串被认为是防御性编程的标志之一,在大多数情况下,你将要拒绝不符合你期望的字符串输入。

一个相当常见的情况是你只想在输入字符串中允许使用字母数字字符,因此我们将使用它作为示例。在普通的 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。