Java8中的无干扰示例

Java8中的无干扰示例,java,java-8,java-stream,Java,Java 8,Java Stream,根据,我们可以修改源,而不是干扰: 您可以修改流元素本身,不应将其称为“干扰” 根据"守则", List<String> list = new ArrayList<>(); list.add("test"); list.forEach(x -> list.add(x)); 不会抛出ConcurrentModificationException,即使它实际上更改了源代码 而这个代码, Employee[] arrayOfEmps = {

根据,我们可以修改源,而不是干扰:

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

根据"守则",

List<String> list = new ArrayList<>();
  list.add("test");
  list.forEach(x -> list.add(x));
不会抛出
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);

所以,我不太明白什么类型的修改允许源代码,什么类型的修改不允许。查看一个干扰并产生有状态和副作用的流的示例将非常有帮助,并正确指示哪个流是哪个流。

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

第二个示例试图通过在
管道期间向源添加元素来进行干扰。但是,由于尝试将元素添加到固定大小的
列表中(该列表由
数组.asList
返回),因此会得到
不支持的操作异常
而不是
ConcurrentModificationException

将第二个示例更改为:

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);
List li=newarraylist(Arrays.asList(arrayOfEmps));
li.stream().map(s->{s.setName(“newname”);li.add(s);返回s;}).limit(10).forEach(System.out::print);

您应该获得
ConcurrentModificationException

您不能更改正在处理的列表的大小

在第一个示例中,您正在更改列表中Employee对象的值

第二步是在列表中添加一项


这就是区别

您的代码正在修改stream元素,而不是列表本身:

s->{s.setName(“newname”)
更改流元素中的字段名,这不会干扰流或其源

java.lang.UnsupportedOperationException
也是不相关的,这是因为您试图在固定大小的列表上调用
add
(这是
Arrays.asList
的结果)。
任何时候对数组的结果调用
add
remove
,asList
,都会引发不支持的操作异常,因为collect的大小是固定的。

您的第一个示例不会修改初始列表

流只是列表上的一个视图,因此初始列表根本不受流代码的影响

而第二个示例明确使用了
list.add()

这就是一切。

当您这样做时:

li.stream().map(s->{s.setName(“newname”);返回s;})

您没有更改列表本身,而是更改了该列表中的一个元素,因此它不会像您预期的那样触发
ConcurrentModificationException

在最后一段代码中,您使用的是
Array.asList

您必须知道
Array.asList
在数组(特定的内部ArrayList类)上返回一个只读包装器,解释为什么不支持
add

实际上,这个内部类并没有通过设计重写AbstractList#add方法;导致
不支持操作异常
;并且仍然没有像您预期的那样
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);
} 
publicstaticvoidmain(字符串[]args){
员工[]arrayOfEmps={
新员工(1名,“杰夫·贝佐斯”)
};
员工el=新员工(11,“比尔·盖茨”);
List li=new ArrayList(Arrays.asList(arrayOfEmps));//避免只读限制
li.stream().peek(s->li.add(el)).forEach(System.out::print);
} 
请注意,我正在包装
数组。List
返回一个“true”
ArrayList
,允许写入,因为这一个实现了
add
方法;)

这被称为
流的源的结构性非结构性更改。例如
ArrayList
文档说:

仅仅设置元素的值并不是结构修改

因此,在您的示例中,这意味着更改
员工
本身不会更改
列表
本身(不会删除或添加元素)。但是更改
列表
本身将失败,出现
ConcurrentModificationException

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

list.stream().forEach(x -> list.remove(x));

这不会因为
ConcurrentModificationException

而失败。哇!已经有很多答案了。有人能发布一个包含状态、干扰、副作用行为的示例代码来获得接受的ans答案吗?请!这也被称为非结构性修改
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);
} 
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);

list.stream().forEach(x -> list.remove(x));
 ConcurrentHashMap<Integer, String> chm = new ConcurrentHashMap<>();
 chm.put(1, "one");
 chm.put(2, "two");
 chm.put(3, "three");

 chm.entrySet().stream()
         .forEach(x -> chm.remove(x.getKey()));