Java Stream 匹配
最后修改于 2025 年 5 月 25 日
本文演示了如何使用 Java Stream 的匹配操作:anyMatch、allMatch 和 noneMatch 来检查流中的条件。
Stream 匹配操作是终端操作,用于检查流中的元素是否满足特定条件。 它们返回一个布尔值,并且具有短路特性(可能提前终止,而无需处理所有元素)。
基本匹配操作
这三个匹配方法具有相似的签名
boolean anyMatch(Predicate<? super T> predicate) boolean allMatch(Predicate<? super T> predicate) boolean noneMatch(Predicate<? super T> predicate)
anyMatch
如果任何元素匹配谓词则返回 true。 allMatch
如果所有元素都匹配则返回 true。 noneMatch
如果没有元素匹配则返回 true。
anyMatch - 检查是否存在
下一个示例使用 anyMatch
来检查是否有任何元素满足条件。
void main() { List<Integer> numbers = List.of(2, 4, 6, 8, 10); boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0); System.out.println("Contains even numbers? " + hasEven); boolean hasOdd = numbers.stream().anyMatch(n -> n % 2 != 0); System.out.println("Contains odd numbers? " + hasOdd); }
此示例检查列表是否包含任何偶数(在本例中为全部)以及任何奇数(在本例中为无)。 anyMatch
在找到第一个匹配项后停止处理。
$ java Main.java Contains even numbers? true Contains odd numbers? false
allMatch - 通用条件
我们可以使用 allMatch
来验证所有元素是否都满足条件。
void main() { List<String> words = List.of("apple", "banana", "avocado", "apricot"); boolean allStartWithA = words.stream().allMatch(s -> s.startsWith("a")); System.out.println("All words start with 'a'? " + allStartWithA); boolean allLongerThan3 = words.stream().allMatch(s -> s.length() > 3); System.out.println("All words longer than 3 chars? " + allLongerThan3); }
此示例检查所有单词是否以 'a' 开头(false)以及所有单词是否都长于 3 个字符(true)。 allMatch
在找到第一个不匹配的元素后停止处理。
$ java Main.java All words start with 'a'? false All words longer than 3 chars? true
noneMatch - 缺席验证
我们可以使用 noneMatch
来确保没有元素满足条件。
void main() { List<Integer> temperatures = List.of(22, 24, 19, 21, 25); boolean noneBelowZero = temperatures.stream().noneMatch(t -> t < 0); System.out.println("No temperatures below zero? " + noneBelowZero); boolean noneAbove30 = temperatures.stream().noneMatch(t -> t > 30); System.out.println("No temperatures above 30? " + noneAbove30); }
此示例验证没有温度低于零(true),也没有温度高于 30(true)。 noneMatch
在找到第一个匹配的元素后停止处理。
$ java Main.java No temperatures below zero? true No temperatures above 30? true
空流行为
下一个示例展示了匹配操作在空流中的行为。
void main() { List<String> emptyList = List.of(); boolean any = emptyList.stream().anyMatch(s -> true); boolean all = emptyList.stream().allMatch(s -> false); boolean none = emptyList.stream().noneMatch(s -> true); System.out.println("anyMatch: " + any); System.out.println("allMatch: " + all); System.out.println("noneMatch: " + none); }
此示例演示了空流的行为:anyMatch
返回 false,allMatch
返回 true(当然是 true),noneMatch
返回 true。
$ java Main.java anyMatch: false allMatch: true noneMatch: true
复杂对象匹配
下一个示例演示了对自定义对象列表的匹配操作,使用 record 类来表示产品。
record Product(String name, double price, boolean inStock) {} void main() { List<Product> inventory = List.of( new Product("Laptop", 999.99, true), new Product("Phone", 699.99, false), new Product("Tablet", 349.99, true) ); boolean anyExpensive = inventory.stream() .anyMatch(p -> p.price() > 800); System.out.println("Any expensive products? " + anyExpensive); boolean allInStock = inventory.stream() .allMatch(Product::inStock); System.out.println("All products in stock? " + allInStock); boolean noneFree = inventory.stream() .noneMatch(p -> p.price() == 0); System.out.println("No free products? " + noneFree); }
此示例检查 Product 对象列表的各种条件,演示了匹配操作如何处理对象属性上的复杂谓词。
$ java Main.java Any expensive products? true All products in stock? false No free products? true
短路行为
下一个示例演示了匹配操作的短路特性。
void main() { boolean result = IntStream.range(1, 1000) .peek(n -> System.out.println("Processing: " + n)) .anyMatch(n -> n % 42 == 0); System.out.println("Found multiple of 42? " + result); }
此示例显示了 anyMatch
在找到第一个 42 的倍数后停止处理。 peek 操作显示实际处理了哪些数字。
$ java Main.java Processing: 1 Processing: 2 ... Processing: 42 Found multiple of 42? true
与其他操作结合使用
下一个示例将匹配操作与其他流操作结合起来,以演示它们的灵活性。
void main() { List<String> mixed = List.of("1", "2", "three", "4", "five"); boolean allNumeric = mixed.stream() .map(s -> { System.out.println("Mapping: " + s); return s; }) .filter(s -> s.length() == 1) .allMatch(s -> Character.isDigit(s.charAt(0))); System.out.println("All single chars are digits? " + allNumeric); }
此示例检查是否所有单字符字符串都是数字,演示了匹配操作如何处理转换后的流。 请注意处理顺序。
$ java Main.java Mapping: 1 Mapping: 2 Mapping: three Mapping: 4 Mapping: five All single chars are digits? true
来源
在本文中,我们探讨了 Java Stream 的匹配操作。 anyMatch、allMatch 和 noneMatch 提供了强大的方法来检查流元素上的条件,并具有高效的短路行为。 这些操作对于编写简洁高效的基于流的条件检查至关重要。
作者
列出所有Java教程。