Non-terminal forEach() in a stream?

会有一股神秘感。 提交于 2019-12-03 22:44:22

Yes there is. It is called peek() (example from the JavaDoc):

Stream.of("one", "two", "three", "four")
     .peek(e -> System.out.println("Original value: " + e))
     .filter(e -> e.length() > 3)
     .peek(e -> System.out.println("Filtered value: " + e))
     .map(String::toUpperCase)
     .peek(e -> System.out.println("Mapped value: " + e))
     .collect(Collectors.toList());

No, there is not.

peek() will only operate on all elements when forced to by a following operation. Can you predict what will be printed by this code?

public class Test
{
    private static final AtomicBoolean FLAG = new AtomicBoolean(false);

    private static void setFlagIfGreaterThanZero(int val)
    {
        if (val > 0) {
            FLAG.set(true);
        }
    }

    public static void main(String[] args)
    {
        FLAG.set(false);

        // Test 1
        IntStream.range(0, 10)
                 .peek(Test::setFlagIfGreaterThanZero)
                 .findFirst();

        System.out.println(FLAG.get());
        FLAG.set(false);

        // Test 2
        IntStream.range(0, 10)
                 .peek(Test::setFlagIfGreaterThanZero)
                 .sorted()
                 .findFirst();

        System.out.println(FLAG.get());
        FLAG.set(false);

        // Test 3
        IntStream.range(0, 10)
                 .boxed()
                 .peek(Test::setFlagIfGreaterThanZero)
                 .sorted()
                 .findFirst();

        System.out.println(FLAG.get());
        FLAG.set(false);

        // Test 4
        IntStream.range(0, 10)
                 .peek(Test::setFlagIfGreaterThanZero)
                 .filter(x -> x == 0)
                 .toArray();

        System.out.println(FLAG.get());
    }
}

The answer is:

false
false
true
true

That output might be intuitive if you have a solid understanding of Java Streams, but hopefully it also indicates that it's a very bad idea to rely on peek() as a mid-stream forEach().

map() also suffers the same issue. As far as I'm aware, there is no Stream operation that guarantees a sort of "process every element without taking shortcuts" behavior in every case independent of the prior and following operations.

Although this can be a pain, the short-circuiting behavior of Streams is an important feature. You might find this excellent answer to be useful: https://stackoverflow.com/a/32194320/507761

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!