Java 使用anyMatch、allMatch与noneMatch方法

Java 使用anyMatch、allMatch与noneMatch方法,用户希望确定流中是否有元素匹配 Predicate,或全部元素匹配 Predicate,或没有元素匹配 Predicate。使用 java.util.stream.Stream 接口定义的 anyMatchallMatchnoneMatch 方法,每种方法返回一个布尔值。

Java 使用anyMatch、allMatch与noneMatch方法 问题描述

用户希望确定流中是否有元素匹配 Predicate,或全部元素匹配 Predicate,或没有元素匹配 Predicate

Java 使用anyMatch、allMatch与noneMatch方法 解决方案

使用 java.util.stream.Stream 接口定义的 anyMatchallMatchnoneMatch 方法,每种方法返回一个布尔值。

Java 使用anyMatch、allMatch与noneMatch方法 具体实例

anyMatchallMatchnoneMatch 方法的签名如下:

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,则值显然为合数;如果返回 truecertainty 参数就派上用场了。
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 方法,并认定集合中的数字均不满足谓词。
anyMatchallMatchnoneMatch 方法能方便地对特定条件下的值流进行校验。
不过,有一个可能引起问题的边缘条件应予注意。如例 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 的描述,对于 allMatchnoneMatch 方法,“流为空将返回 true 且不再评估谓词”,因此两种方法中的谓词可以是任何值。而对于 anyMatch 方法,流为空将返回 false,这可能导致错误诊断异常困难,所以应用时务须谨慎。

如果流为空,无论提供的谓词是什么,allMatchnoneMatch 方法将返回 true,而 anyMatch 方法将返回 false。三种方法在流为空时都不会评估任何提供的谓词。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程