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()));