Inclusive takeWhile() for Streams

后端 未结 2 427
被撕碎了的回忆
被撕碎了的回忆 2021-01-15 10:25

I want to know if there is a way to add the last element of the stream that was tested against the condition of the method takeWhile(). I believe I want to achieve something

相关标签:
2条回答
  • 2021-01-15 10:44

    I add an horrible approach that might be overkill for your (or any) use case, but just for fun.

    public static void main(String[] args) {
        List<Integer> source = List.of(1, 3, 2, 5, 4, 6);
        Iterator<Integer> iterator = source.iterator();
        AtomicBoolean proceed = new AtomicBoolean(true);
    
        Stream
            .generate(() -> {
                if (!proceed.get() || !iterator.hasNext()) {
                    return null;
                }
                int value = iterator.next();
                System.out.println("generate: " + value);
                proceed.set(value < 5);
                return value;
            })
            .takeWhile(Objects::nonNull)
            .forEach(bar -> System.out.println("forEach: " + bar));
    
    }
    

    The output will be:

    generate: 1
    forEach: 1
    generate: 3
    forEach: 3
    generate: 2
    forEach: 2
    generate: 5
    forEach: 5
    

    Probably the worst thing about this approach is that it gives generate() a responsibility (checking if there are more) that it does not belong with it.

    0 讨论(0)
  • 2021-01-15 10:57

    There's no convenient way to do that with the normal stream API. It is possible in an ugly way (you would need to adapt this implementation, that's just a normal takeWhile "backported" for Java 8).

    This guy has written a stream extension library which has takeWhileInclusive.

    Sample usage:

    IntStreamEx.of(1, 3, 2, 5, 4, 6)
        .peek(foo -> System.out.println("Peek: " + foo))
        .takeWhileInclusive(n -> n < 5)
        .forEach(bar -> System.out.println("forEach: " + bar));
    
    0 讨论(0)
提交回复
热议问题