1. 引言

本文将探讨如何在Java中通过正则表达式(regex)过滤现有列表,创建新列表。我们将学习多种使用Java正则表达式实现列表过滤的方法,并分析不同场景下的最佳实践。

2. 正则表达式基础

正则表达式是用于匹配字符串中特定字符序列的模式。作为多功能工具,它们支持文本过滤、操作、替换和验证等操作。

Java通过java.util.regex包提供了强大的正则表达式功能支持。

2.1 常用特殊字符

通过组合特殊字符构建匹配模式:

  • ".":匹配任意字符(换行符除外)
  • "*":匹配前一个字符零次或多次
  • "+":匹配前一个字符一次或多次
  • "?":匹配前一个字符零次或一次
  • "^":匹配字符串开头
  • "$":匹配字符串结尾
  • "[]":匹配括号内任意字符,如"[abc]"匹配abc
  • "|":逻辑或操作,如"a|b"匹配ab
  • "()":用于分组

2.2 常用正则简写符号

在Java中需使用双反斜杠"\\"转义特殊字符构造。以下是常用模式的简写符号:

  • "\\d":匹配数字[0-9]
  • "\\w":匹配单词字符[a-zA-Z_0-9]
  • "\\s":匹配空白字符(空格、制表符、换行符)
  • "\\D":匹配非数字字符
  • "\\W":匹配非单词字符
  • "\\S":匹配非空白字符

3. Java中使用正则过滤列表的方法

正则表达式字符串内部会被编译为确定性有限自动机(DFA)或非确定性有限自动机(NFA)。匹配器使用该状态机遍历并匹配输入字符串。

3.1 使用Stream API结合Pattern和Predicate

Java Stream API提供便捷的列表过滤方式,可结合Pattern.compile()实现正则过滤:

List<String> filterWithStreamPattern() {
    List<String> fruits = List.of("apple", "banana", "apricot", "avocado", "berry");
    Pattern pattern = Pattern.compile("^a.*");

    return fruits.stream()
      .filter(pattern.asPredicate())
      .toList();
}

此代码筛选以"a"开头的字符串,返回结果:[apple, apricot, avocado]

3.2 使用String.matches()方法

利用String.matches()方法匹配整个字符串,返回布尔值:

List<String> filterUsingStringMatches() {
    List<String> list = List.of("123", "abc", "456def", "789", "xyz");

    return list.stream()
      .filter(str -> str.matches("\\d+")).toList();
}

创建包含一个或多个数字的新列表,结果为:[123, 789]

3.3 结合循环使用Pattern.compile()

对于JDK 8以下版本(无法使用Stream API),可通过循环结合Pattern.matcher()实现:

List<String> filterUsingPatternCompile() {
    List<String> numbers = List.of("one", "two", "three", "four", "five");
    List<String> startWithTList = new ArrayList<>();

    Pattern pattern = Pattern.compile("^t.*");

    for (String item : numbers) {
        Matcher matcher = pattern.matcher(item);
        if (matcher.matches()) {
            startWithTList.add(item);
        }
    }

    return startWithTList;
}

筛选以"t"开头的字符串,结果为:[two, three]

3.4 使用Collectors.partitioningBy()进行条件分组

通过Stream API结合Pattern.compile()实现条件分组:

Map<Boolean, List<String>> filterUsingCollectorsPartitioningBy() {
    List<String> fruits = List.of("apple", "banana", "apricot", "berry");

    Pattern pattern = Pattern.compile("^a.*");

    return fruits.stream()
      .collect(Collectors.partitioningBy(pattern.asPredicate()));
}

筛选以"a"开头的元素,结果为: ✅ 匹配项(key=true):[apple, apricot]
❌ 未匹配项(key=false):[banana, berry]

4. 结论

本文展示了多种使用正则表达式过滤列表的技术。在众多方案中,Stream API因其可读性和简洁语法脱颖而出

结合PatternPredicate的方式尤其高效,特别是在处理大数据集时——因为Pattern只需编译一次即可重复使用,节省处理时间。

此外,Stream API支持无缝链式操作,性能表现优异。当然,具体场景下也可选择其他方法,但Stream API通常能在代码清晰度和性能之间取得最佳平衡。

⚠️ 踩坑提示:在Java中使用正则时,务必注意字符串中的反斜杠需要双重转义(如"\\d"而非"\d"),这是新手常犯的错误。


原始标题:Filtering a List With Regular Expressions in Java | Baeldung