Java 8中的非干扰示例

ama*_*ish 12 java java-8 java-stream

根据这个问题,我们可以修改源,它不称为干扰:

您可以修改流元素本身,不应将其称为"干扰".

根据这个问题,代码

List<String> list = new ArrayList<>();
  list.add("test");
  list.forEach(x -> list.add(x));
Run Code Online (Sandbox Code Playgroud)

会扔ConcurrentModificationException.

但我的代码,

Employee[] arrayOfEmps = {
                new Employee(1, "Jeff Bezos"),
                new Employee(2, "Bill Gates"),
                new Employee(3, "hendry cavilg"),
                new Employee(4, "mark cuban"),
                new Employee(5, "zoe"),
                new Employee(6, "billl clinton"),
                new Employee(7, "ariana") ,
                new Employee(8, "cathre"),
                new Employee(9, "hostile"),
                new Employee(10, "verner"),
            };
        Employee el=new Employee(1, "Jeff Bezos");
        List<Employee> li=Arrays.asList(arrayOfEmps);
        li.stream().map(s->{s.setName("newname");return s;}).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

ConcurrentModificationException即使它实际上改变了源,也不会抛出.

而这段代码,

Employee[] arrayOfEmps = {
                new Employee(1, "Jeff Bezos"),
                new Employee(2, "Bill Gates"),
                new Employee(3, "hendry cavilg"),
                new Employee(4, "mark cuban"),
                new Employee(5, "zoe"),
                new Employee(6, "billl clinton"),
                new Employee(7, "ariana") ,
                new Employee(8, "cathre"),
                new Employee(9, "hostile"),
                new Employee(10, "verner"),
            };
        Employee el=new Employee(1, "Jeff Bezos");
        List<Employee> li=Arrays.asList(arrayOfEmps);
        li.stream().map(s->{s.setName("newname");li.add(s);return s;}).limit(10).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(Unknown Source)
    at java.util.AbstractList.add(Unknown Source)
    at java8.Streams.lambda$0(Streams.java:33)
    at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source)
    at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
    at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
    at java.util.stream.ReferencePipeline.forEach(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

所以,我并不完全明白哪些类型的修改允许来源,哪些不允许.看到一个干扰并产生有状态和副作用的产生流的例子将是非常有帮助的,并且适当地指示哪个是哪个.

Mik*_*378 12

当你这样做:

li.stream().map(s->{s.setName("newname");return s;})

你没有改变列表本身,而是改变了这个列表中的元素 ; 所以它不会ConcurrentModificationException像你期望的那样触发.

在最后一个代码段中,您正在使用Array.asList.
您必须知道在数组(特定的内部ArrayList类)上Array.asList返回仅仅是只读的包装器,解释了为什么不受支持. add

实际上,这个内部类没有按设计覆盖AbstractList #add方法; 引起UnsupportedOperationException; 仍然没有ConcurrentModificationException你想象的那样.

这是一个类似于你的最后一个片段的例子,它会抛出一个ConcurrentModificationException:

public static void main(String[] args) {
    Employee[] arrayOfEmps = {
      new Employee(1, "Jeff Bezos")
    };
    Employee el = new Employee(11, "Bill Gates");
    List<Employee> li = new ArrayList<>(Arrays.asList(arrayOfEmps)); // to avoid read-only restriction
    li.stream().peek(s -> li.add(el)).forEach(System.out::print);
} 
Run Code Online (Sandbox Code Playgroud)

请注意,我Arrays.List用"true" 包装返回ArrayList,允许写入,因为这个实现了add方法;)

  • 这也称为非结构修改 (2认同)

Era*_*ran 5

您的第一个示例更改了现有元素Stream,但未添加或删除源中的元素.因此,这不是干扰.

您的第二个示例尝试通过在Stream管道期间向源添加元素来进行干扰.但是,您可以使用UnsupportedOperationException而不是ConcurrentModificationException,因为您尝试将元素添加到固定大小List(由返回的Arrays.asList).

将您的第二个示例更改为:

List<Employee> li=new ArrayList<>(Arrays.asList(arrayOfEmps));
li.stream().map(s->{s.setName("newname");li.add(s);return s;}).limit(10).forEach(System.out::print);
Run Code Online (Sandbox Code Playgroud)

你应该得到ConcurrentModificationException.