为什么 Stream.allMatch() 为空流返回 true?

2022-08-31 10:10:41

我和我的同事遇到了一个错误,这是由于我们假设空流调用将返回。allMatch()false

if (myItems.allMatch(i -> i.isValid()) { 
    //do something
}

当然,假设而不阅读文档是我们的错。但是我不明白的是,为什么空流的默认行为返回 。这是什么原因呢?与 (相反返回 false) 一样,此操作以一种命令式方式使用,该方式离开 monad,并可能在语句中使用。考虑到这些事实,有什么理由让默认为空流对于大多数用途是可取的?allMatch()trueanyMatch()ifallMatch()true


答案 1

这被称为空洞的真理。空集合的所有成员都符合您的条件;毕竟,你能指出一个没有的吗?

同样,返回 ,因为找不到与条件匹配的集合元素。这让很多人感到困惑,但事实证明,这是为空集定义“任何”和“全部”的最有用和最一致的方式。anyMatchfalse


答案 2

这是另一种思考方式:

allMatch()是到什么就是到什么&&sum()+

请考虑以下逻辑语句:

IntStream.of(1, 2).sum() + 3 == IntStream.of(1, 2, 3).sum()
IntStream.of(1).sum() + 2 == IntStream.of(1, 2).sum()

这是有道理的,因为这只是 的泛化。但是,再删除一个元素时会发生什么情况?sum()+

IntStream.of().sum() + 1 == IntStream.of(1).sum()

我们可以看到,以特定的方式定义 或空数字序列的总和是有意义的。这给了我们求和的“单位元”,或者当添加到某物中时没有效果的值()。IntStream.of().sum()0

我们可以将相同的逻辑应用于代数。Boolean

Stream.of(true, true).allMatch(it -> it) == Stream.of(true).allMatch(it -> it) && true

更一般地说:

stream.concat(Stream.of(thing)).allMatch(it -> it) == stream.allMatch(it -> it) && thing

如果那么这个规则仍然需要适用。我们可以使用 && 的“身份元素”来解决这个问题。所以。stream = Stream.of()true && thing == thingStream.of().allMatch(it -> it) == true


推荐