Java Stream关闭方法模糊行为

时间:2018-06-15 11:03:28

标签: java java-8 stream java-stream

鉴于此Java类:

class MyClass {
    private int value;

    public MyClass(int value) {
        this.value = value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    @Override
    public String toString() {
        return "Value: " + value;
    }
}

并且给出了这个Java代码:

Consumer<MyClass> cons = mc -> mc.setValue(mc.getValue() * mc.getValue());

List<MyClass> list = new ArrayList<>();
list.add(new MyClass(1));
list.add(new MyClass(2));
list.add(new MyClass(3));

System.out.println(list);

我得到了这个输出:[值:1,值:2,值:3]

当我运行此代码时:

list.stream().peek(cons).close();   //1
System.out.println(list);

我期待作为输出[值:1,值:4,值:9],但我得到[值:1,值:2,值:3], 所以列表中的元素没有被修改。

但是当我跑这个时:

list.stream().forEach(cons);        //2

和此:

list.stream().peek(cons).count();   //3

我得到了我预期的输出([值:1,价值:4,价值:9])

为什么不行// 1给我这个输出?我想这是因为close():这个方法是如何工作的?

感谢您的支持。

2 个答案:

答案 0 :(得分:4)

close,无论是否有终端操作,都会被触发;如果在try with resourceclose中使用它,则会在流本身上调用它;但无论哪种方式,它都不是终端操作。所以它既不是intermediate也不是terminal - 它有点特别。

    Stream<Integer> s2 = Stream.of(1, 2, 3);
    s2.onClose(() -> System.out.println("Closing 2"));
    s2.close(); // will print Closing 2

但也看到了这个:

    try (Stream<Integer> s = Stream.of(1, 2, 3)) {
        s.onClose(() -> System.out.println("Closing"));
        s.filter(x -> x > 1)
         .peek(x -> System.out.println("foud one"));
    }

运行此操作并亲自了解第二个示例peek未触发,但close是。

因此,要回答您的问题,正确的措辞是:close不是终端操作,因此您的流管道不会被执行。

答案 1 :(得分:0)

peek是一个中间操作,除非您有终端操作符,否则不会触发流处理管道。所以声明,

list.stream().peek(cons).close();

没有终端操作,并且根本没有触发流管道,因此不执行消费者,导致您观察到的结果。该清单保持不变。但是,这不是由于流中的close方法。

在其他两个例子中,

list.stream().forEach(cons);        
list.stream().peek(cons).count();  

您有终端操作forEachcount,因此会执行使用者导致修改原始列表。