将 allMatch、noneMatch 和 anyMatch 合并到单个流上

2024-05-13

我想要以下逻辑:(我知道它不起作用,因为它多次消耗流)。但我不知道如何实现它。

Stream<ByteBuffer> buffers = super.getBuffers().stream();
if (buffers.allMatch(b -> b.position() > 0)) {
    return OutgoingMessageStatus.FULLY_SENT;
} else if (buffers.noneMatch(b -> b.position() > 0)) {
    return OutgoingMessageStatus.WAS_NOT_SENT;
} else {
    return OutgoingMessageStatus.PARTIALLY_SENT;
}

我怎样才能做到这一点?


由于结果super.getBuffers() is List<ByteBuffer>,你可以迭代它两次。

List<ByteBuffer> buffers = super.getBuffers();
if (buffers.stream().allMatch(b -> b.position() > 0)) {
    return OutgoingMessageStatus.FULLY_SENT;
} else if (buffers.stream().noneMatch(b -> b.position() > 0)) {
    return OutgoingMessageStatus.WAS_NOT_SENT;
} else {
    return OutgoingMessageStatus.PARTIALLY_SENT;
}

请注意,这仍然不需要在所有情况下迭代所有元素。allMatch一旦遇到不匹配的元素就返回,noneMatch一旦遇到匹配的元素就返回。所以在PARTIALLY_SENT在这种情况下,有可能在没有考虑所有要素的情况下得出结论。

另一种选择是

List<ByteBuffer> buffers = super.getBuffers();
if(buffers.isEmpty()) return OutgoingMessageStatus.FULLY_SENT;
Predicate<ByteBuffer> p = b -> b.position() > 0;
boolean sent = p.test(buffers.get(0));
if(!sent) p = p.negate();
return buffers.stream().skip(1).allMatch(p)? sent?
    OutgoingMessageStatus.FULLY_SENT:
    OutgoingMessageStatus.WAS_NOT_SENT:
    OutgoingMessageStatus.PARTIALLY_SENT;
}

第一个元素的状态决定了我们必须检查哪个条件。一旦出现矛盾因素,allMatch立即返回,我们有一个PARTIALLY_SENT情况。否则,所有元素都像第一个元素一样匹配,这意味着“全部发送”或“无发送”。

对空列表的预检查会产生与原始代码相同的行为,并确保get(0)永远不会破裂。


如果您确实有一个 Stream 而不是可以多次迭代的源,则没有简单的捷径解决方案,因为这需要有状态谓词。然而,有一些简单的解决方案可以处理所有元素。

Map<Boolean,Long> result=getBuffers().stream()
    .collect(Collectors.partitioningBy(b -> b.position() > 0, Collectors.counting()));
return
    result.getOrDefault(false, 0L)==0?
        OutgoingMessageStatus.FULLY_SENT:
    result.getOrDefault(true, 0L)==0?
        OutgoingMessageStatus.WAS_NOT_SENT:
        OutgoingMessageStatus.PARTIALLY_SENT;

or

return super.getBuffers().stream()
    .map(b -> b.position() > 0?
              OutgoingMessageStatus.FULLY_SENT: OutgoingMessageStatus.WAS_NOT_SENT)
    .reduce((a,b) -> a==b? a: OutgoingMessageStatus.PARTIALLY_SENT)
    .orElse(OutgoingMessageStatus.FULLY_SENT);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 allMatch、noneMatch 和 anyMatch 合并到单个流上 的相关文章

随机推荐