代码之家  ›  专栏  ›  技术社区  ›  Valix85

Java流关闭方法模糊行为

  •  1
  • Valix85  · 技术社区  · 6 年前

    给定这个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);
    

    我期望输出[value:1,value:4,value:9],但是我得到了[value:1,value:2,value:3], 所以列表中的元素没有被修改。

    但是当我运行这个时:

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

    而这:

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

    我两次都得到了预期的输出([值:1,值:4,值:9])。

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

    谢谢你的支持。

    2 回复  |  直到 6 年前
        1
  •  4
  •   Eugene    6 年前

    close ,将被触发,无论是否有终端操作;如果它用于 try with resource 关闭 在流本身上调用;但不管怎样,它都不是终端操作。所以它既不是 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 不会触发,但是 关闭 是。

    所以要回答你的问题,正确的措辞应该是: 关闭 不是终端操作,因此不会执行流管道。

        2
  •  0
  •   Ravindra Ranwala    6 年前

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

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

    没有终端操作,流管道根本不会触发,因此不会执行使用者,从而导致观察到的结果。列表保持不变。但这并不是因为 close 流中的方法。

    在其他两种情况下,

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

    你有终端操作 forEach count ,因此执行使用者,从而修改原始列表。