为什么Stream.allMatch()对于空stream返回true?
我的同事和我有一个错误是由于我们的假设,一个空的stream调用allMatch()
将返回false
。
if (myItems.allMatch(i -> i.isValid()) { //do something }
当然,假设和不读文档是我们的错。 但是我不明白为什么空stream的默认allMatch()
行为返回true
。 这是什么原因? 和anyMatch()
(相反地返回false)一样,这个操作是以一种命令的方式来使用的,它离开monad,可能用在if
语句中。 考虑到这些事实,是否有任何理由为什么allMatch()
默认为true
空stream是可取的大多数用途?
这被称为空洞的真相 。 所有空集合的成员满足您的条件; 毕竟,你能指出一个不是吗? 同样, anyMatch
返回false,因为您找不到符合条件的集合元素。 这让很多人感到困惑,但事实certificate,这是定义空集“任意”和“全部”的最有用和最一致的方法。
当我调用list.allMatch
(或其他语言的list.allMatch
语言)时,我想检测list
任何项目是否与谓词不匹配。 如果没有项目,则可能无法匹配。 我的下面的逻辑会select项目,并期望他们已经匹配的谓词。 对于一个空的列表,我会select任何项目,逻辑将仍然是健全的。
如果allMatch
为空列表返回false
?
我直截了当的逻辑会失败:
if (!myList.allMatch(predicate)) { throw new InvalidDataException("Some of the items failed to match!"); } for (Item item : myList) { ... }
我需要记住用!myList.empty() && !myList.allMatch()
replace检查。
简而言之, allMatch
对于一个空列表返回true
不仅在逻辑上是合理的,而且还在于快乐的执行path,所以需要更less的检查。
看起来它的基础是math归纳。 对于计算机科学来说,这可能是一个recursionalgorithm的基本情况。
如果这个stream是空的,则量化被认为是真实的满足,并且总是如此。 Oracle Docs:stream操作和pipe道
这里的关键在于它“天真地满意”,这本质上有点误导。 维基百科有一个体面的讨论。
在纯粹的math中,真实的真实陈述本身通常并不感兴趣,但是它们经常作为math归纳certificate的基本情况而出现。 维基百科:真实的真相
这是另一种思考方式:
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)的价值。
我们可以将相同的逻辑应用于布尔代数。
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 == thing
,所以Stream.of().allMatch(it -> it) == true
。