Java 使用anyMatch、allMatch与noneMatch方法,用户希望确定流中是否有元素匹配 Predicate
,或全部元素匹配 Predicate
,或没有元素匹配 Predicate
。使用 java.util.stream.Stream
接口定义的 anyMatch
、allMatch
与 noneMatch
方法,每种方法返回一个布尔值。
Java 使用anyMatch、allMatch与noneMatch方法 问题描述
用户希望确定流中是否有元素匹配 Predicate
,或全部元素匹配 Predicate
,或没有元素匹配 Predicate
。
Java 使用anyMatch、allMatch与noneMatch方法 解决方案
使用 java.util.stream.Stream
接口定义的 anyMatch
、allMatch
与 noneMatch
方法,每种方法返回一个布尔值。
Java 使用anyMatch、allMatch与noneMatch方法 具体实例
anyMatch
、allMatch
与 noneMatch
方法的签名如下:
boolean anyMatch(Predicate<? super T> predicate)
boolean allMatch(Predicate<? super T> predicate)
boolean noneMatch(Predicate<? super T> predicate)
每种方法的用途不言自明。我们以质数计算器为例进行说明。在大于或等于 2 的自然
数中,如果一个数无法被除 1 和该数自身之外的其他数整除,则这个数为质数(prime number),否则为合数(composite number)。
如例 3-51 所示,为验证某个数是否为质数,一种简单的做法是对从 2 开始到该数平方根的所有数做取模运算,然后取整。
例 3-51 质数校验
public boolean isPrime(int num) {
int limit = (int) (Math.sqrt(num) + 1); ➊
return num == 2 || num > 1 && IntStream.range(2, limit)
.noneMatch(divisor -> num % divisor == 0); ➋
}
❶ 校验上限
❷ 使用 noneMatch
方法
借由 noneMatch
方法,质数校验易如反掌。
BigInteger
类与质数
java.math.BigInteger
类定义的isProbablePrime
方法很有意思,其签名为:boolean isProbablePrime(**int** certainty)
如果
isProbablePrime
方法返回false
,则值显然为合数;如果返回true
,certainty
参数就派上用场了。
certainty
的值表示调用程序可以容忍的不确定性。如果isProbablePrime
方法返回true
,则一个数实际为质数的概率将超过1 - 1/2^{certainty}
。因此,certainty
等于 2 意味着概率为 0.75,certainty
等于 3 意味着概率为 0.875,certainty
等于 4 意味着概率为 0.9375,等于 5 意味着概率为 0.96875,以此类推。
certainty
参数的值越大,isProbablePrime
方法的执行时间越长。
例 3-52 显示了质数校验的两种方案。
例 3-52 针对质数计算的测试
private Primes calculator = new Primes();
@Test ➊
public void testIsPrimeUsingAllMatch() throws Exception {
assertTrue(IntStream.of(2, 3, 5, 7, 11, 13, 17, 19)
.allMatch(calculator::isPrime));
}
@Test ➋
public void testIsPrimeWithComposites() throws Exception {
assertFalse(Stream.of(4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20)
.anyMatch(calculator::isPrime));
}
❶ 为简单起见,使用 allMatch
方法
❷ 使用合数进行测试
第一个测试调用已知质数流中的 allMatch
方法(参数为 Predicate
),仅当所有值均为质数时返回 true
。
第二个测试对一个合数集合使用 anyMatch
方法,并认定集合中的数字均不满足谓词。
anyMatch
、allMatch
与 noneMatch
方法能方便地对特定条件下的值流进行校验。
不过,有一个可能引起问题的边缘条件应予注意。如例 3-53 所示,三种方法在作用于空流(empty stream)时的行为不那么直观。
例 3-53 针对空流的测试
@Test
public void emptyStreamsDanger() throws Exception {
assertTrue(Stream.empty().allMatch(e -> false));
assertTrue(Stream.empty().noneMatch(e -> true));
assertFalse(Stream.empty().anyMatch(e -> true));
}
根据 Javadoc 的描述,对于 allMatch
和 noneMatch
方法,“流为空将返回 true
且不再评估谓词”,因此两种方法中的谓词可以是任何值。而对于 anyMatch
方法,流为空将返回 false
,这可能导致错误诊断异常困难,所以应用时务须谨慎。
如果流为空,无论提供的谓词是什么,
allMatch
和noneMatch
方法将返回true
,而anyMatch
方法将返回false
。三种方法在流为空时都不会评估任何提供的谓词。