sla*_*hms 4 java java-8 java-stream
我想有以下逻辑:(我知道它不起作用,因为它不止一次地消耗流).但我不知道如何实现它.
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;
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
由于结果super.getBuffers()为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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,在所有情况下,这仍然不需要迭代所有元素.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;
}
Run Code Online (Sandbox Code Playgroud)
第一个元素的状态决定了我们必须检查的条件.一旦存在矛盾的因素,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;
Run Code Online (Sandbox Code Playgroud)
要么
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);
Run Code Online (Sandbox Code Playgroud)
您可以使用filter(),然后计算通过它的元素数量:
Stream<ByteBuffer> buffers = super.getBuffers().stream();
int matches = buffers.filter(b -> b.position() > 0).count();
if (matches == super.getBuffers().size()) {
return OutgoingMessageStatus.FULLY_SENT;
} else if (matches == 0) {
return OutgoingMessageStatus.WAS_NOT_SENT;
} else {
return OutgoingMessageStatus.PARTIALLY_SENT;
}
Run Code Online (Sandbox Code Playgroud)
这假设Stream( super.getBuffers())的数据源有一个size()方法。如果没有,您可以ByteBuffer使用附加变量(不太优雅,我知道)计算s的总数:
int[] total = {0};
int matches = buffers.filter(b -> {total[0]++; return b.position() > 0;}).count();
if (matches == total[0]) {
return OutgoingMessageStatus.FULLY_SENT;
} else if (matches == 0) {
return OutgoingMessageStatus.WAS_NOT_SENT;
} else {
return OutgoingMessageStatus.PARTIALLY_SENT;
}
Run Code Online (Sandbox Code Playgroud)
这种方法的缺点是当只有一些元素通过过滤器时它不会很快失败(即输出应该是OutgoingMessageStatus.PARTIALLY_SENT)。也许您可以使用一些reduce操作来返回三个可能的输出之一,并且仅根据需要处理尽可能多的元素。