Java – combine allmatch, nonematch, and anymatch on a single stream

I think there is the following logic: (I know it doesn't work because it consumes the stream more than once) But I don't know how to achieve it

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;
}

How can I do this?

Solution

Due to super The result of getbuffers() is list < ByteBuffer >, so you can iterate twice

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;
}

Note that in all cases, this still does not require iterating over all elements Allmatch returns immediately when a non - matching element is encountered, and nonematch returns immediately when a matching element is encountered Therefore, in parallel_ In the case of sent, it may draw conclusions without looking at all the elements

Another option is

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;
}

The state of the first element determines the conditions we must check As long as there are conflicting elements, allmatch returns immediately, and we have a partition_ Sent situation Otherwise, all elements match the first, indicating "all sent" or "not sent"

Pre checking an empty list produces the same behavior as the original code and ensures that get (0) is never interrupted

If you do have a stream instead of a source that can be iterated many times, there is no simple quick solution because this requires stateful predicates However, there are some simple solutions that deal with all elements

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);
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>