鉴于此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():这个方法是如何工作的?
感谢您的支持。
答案 0 :(得分:4)
close
,无论是否有终端操作,都会被触发;如果在try with resource
或close
中使用它,则会在流本身上调用它;但无论哪种方式,它都不是终端操作。所以它既不是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();
您有终端操作forEach
和count
,因此会执行使用者导致修改原始列表。