Java Pattern.asPredicate 方法
上次修改时间:2025 年 4 月 20 日
Pattern.asPredicate 方法在 Java 8 中引入,作为 java.util.regex.Pattern 类的一部分。 它将编译的正则表达式模式转换为 Predicate<String>,用于函数式风格的操作。 此方法在处理 Java Stream 时特别有用。
返回的谓词测试输入字符串是否包含与模式匹配的内容。 这等效于对模式调用 matcher(input).find。 该谓词可以在任何需要 Predicate<String> 的地方使用。
基本定义
Java 中的 Predicate 是一个函数式接口,表示一个参数的布尔值函数。 它通常用于过滤操作。 Pattern 类表示编译的正则表达式。
asPredicate 通过创建一个测试字符串与模式的谓词来桥接这些概念。 该方法要求首先编译该模式。 结果谓词是线程安全的并且可以重复使用。
Basic asPredicate 示例
此示例演示了 asPredicate 的最简单用法。 我们创建一个用于电子邮件验证的模式,并将其用作谓词来测试字符串。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.function.Predicate;
public class BasicPredicateExample {
public static void main(String[] args) {
Pattern emailPattern = Pattern.compile("^[\\w.-]+@[\\w.-]+\\.[a-z]{2,}$");
Predicate<String> emailPredicate = emailPattern.asPredicate();
System.out.println("test@example.com: " + emailPredicate.test("test@example.com"));
System.out.println("invalid.email: " + emailPredicate.test("invalid.email"));
}
}
在此示例中,我们编译一个电子邮件正则表达式模式并将其转换为谓词。 谓词的 test 方法检查输入字符串是否包含与模式匹配的内容。 第一个测试返回 true,而第二个测试返回 false。
使用 asPredicate 过滤 Stream
asPredicate 最强大的用途之一是过滤流。 此示例演示了如何过滤字符串列表以仅包含有效的电话号码。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.List;
import java.util.stream.Collectors;
public class StreamFilterExample {
public static void main(String[] args) {
Pattern phonePattern = Pattern.compile("^\\+?[0-9]{10,15}$");
List<String> contacts = List.of(
"+1234567890", "invalid", "9876543210", "123-456-7890"
);
List<String> validPhones = contacts.stream()
.filter(phonePattern.asPredicate())
.collect(Collectors.toList());
System.out.println("Valid phone numbers: " + validPhones);
}
}
在这里,我们从字符串列表创建一个流,并使用我们的模式谓词对其进行过滤。 只有与电话号码模式匹配的字符串才能通过过滤器。 结果仅包含原始列表中的有效电话号码。
组合谓词
可以使用 Predicate 接口的默认方法将 asPredicate 与其他谓词组合。 此示例演示了如何创建复杂的验证逻辑。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.function.Predicate;
public class CombinedPredicatesExample {
public static void main(String[] args) {
Pattern uppercasePattern = Pattern.compile("[A-Z]");
Pattern digitPattern = Pattern.compile("[0-9]");
Predicate<String> hasUppercase = uppercasePattern.asPredicate();
Predicate<String> hasDigit = digitPattern.asPredicate();
Predicate<String> isStrongPassword = hasUppercase.and(hasDigit)
.and(s -> s.length() >= 8);
System.out.println("Password1: " + isStrongPassword.test("Password1"));
System.out.println("weakpass: " + isStrongPassword.test("weakpass"));
}
}
我们创建两个模式谓词来检查大写字母和数字。 然后,我们使用 and 将它们与长度检查结合起来。 结果谓词仅对满足所有三个条件的字符串返回 true。
不区分大小写的谓词
此示例演示了如何使用模式标志创建不区分大小写的谓词。 无论字母大小写如何,该谓词都将匹配。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.stream.Stream;
public class CaseInsensitivePredicate {
public static void main(String[] args) {
Pattern namePattern = Pattern.compile("john", Pattern.CASE_INSENSITIVE);
Stream.of("John", "JOHN", "john", "Jane")
.filter(namePattern.asPredicate())
.forEach(System.out::println);
}
}
CASE_INSENSITIVE 标志使模式匹配不区分大小写。 该谓词将匹配 "john" 的所有大小写变体,但不匹配其他名称。 打印 "john" 的所有三个大小写变体。
asPredicate 与 asMatchPredicate
Java 11 引入了 asMatchPredicate,它在匹配行为方面与 asPredicate 不同。 此示例比较了两者。
package com.zetcode;
import java.util.regex.Pattern;
public class PredicateComparison {
public static void main(String[] args) {
Pattern wordPattern = Pattern.compile("hello");
String input1 = "hello";
String input2 = "hello there";
System.out.println("asPredicate:");
System.out.println(input1 + ": " + wordPattern.asPredicate().test(input1));
System.out.println(input2 + ": " + wordPattern.asPredicate().test(input2));
System.out.println("\nasMatchPredicate:");
System.out.println(input1 + ": " + wordPattern.asMatchPredicate().test(input1));
System.out.println(input2 + ": " + wordPattern.asMatchPredicate().test(input2));
}
}
asPredicate 的行为类似于 find,匹配字符串中的任何位置。 asMatchPredicate 的行为类似于 matches,要求整个字符串匹配。 两个输入都与 asPredicate 匹配,但只有完全匹配才适用于 asMatchPredicate。
在集合中使用谓词
此示例演示了如何将模式谓词与诸如 removeIf 之类的集合操作一起使用。 我们将从列表中删除所有无效的 ID。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.ArrayList;
import java.util.List;
public class CollectionRemoveExample {
public static void main(String[] args) {
Pattern idPattern = Pattern.compile("^[A-Z]{2}[0-9]{4}$");
List<String> ids = new ArrayList<>(List.of(
"AB1234", "INVALID", "CD5678", "XY90", "EF9012"
));
ids.removeIf(idPattern.asPredicate().negate());
System.out.println("Valid IDs: " + ids);
}
}
我们为有效 ID(2 个字母后跟 4 个数字)创建一个谓词,并使用带有否定谓词的 removeIf 来删除无效条目。 negate 方法反转谓词的逻辑。 列表中仅保留有效的 ID。
使用谓词进行复杂验证
对于更复杂的验证,我们可以链接多个模式谓词。 此示例验证具有特定格式要求的产品代码。
package com.zetcode;
import java.util.regex.Pattern;
import java.util.function.Predicate;
public class ComplexValidationExample {
public static void main(String[] args) {
Pattern startsWithLetter = Pattern.compile("^[A-Z]");
Pattern containsDigit = Pattern.compile("[0-9]");
Pattern endsWithLetter = Pattern.compile("[A-Z]$");
Predicate<String> isValidProductCode = startsWithLetter.asPredicate()
.and(containsDigit.asPredicate())
.and(endsWithLetter.asPredicate())
.and(s -> s.length() >= 5 && s.length() <= 10);
System.out.println("A123B: " + isValidProductCode.test("A123B"));
System.out.println("1ABC: " + isValidProductCode.test("1ABC"));
System.out.println("AB1234567C: " + isValidProductCode.test("AB1234567C"));
}
}
我们将三个模式谓词与长度检查结合起来以验证产品代码。 代码必须以字母开头和结尾,至少包含一个数字,并且长度为 5-10 个字符。 只有满足所有条件的字符串才能通过验证。
来源
Pattern.asPredicate 方法提供了一种强大的方法,可以将正则表达式模式匹配与 Java 的函数式编程功能集成。 它对于现代 Java 代码中的过滤和验证任务特别有用。
作者
列出所有Java教程。