3 回答

TA貢獻1805條經驗 獲得超10個贊
當你這樣做時:
li.stream().map(s->{s.setName("newname");return s;})
您沒有更改列表本身,而是更改了此列表中的一個元素;所以它不會ConcurrentModificationException像你預期的那樣觸發 a 。
在最后一個代碼片段中,您使用的是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);
}
請注意,我Arrays.List用 "true"包裝返回ArrayList,允許寫入,因為它實現了該add方法;)

TA貢獻1757條經驗 獲得超8個贊
您的第一個示例更改 的現有元素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);
你應該得到ConcurrentModificationException.

TA貢獻1848條經驗 獲得超2個贊
這稱為 . 來源的結構性對非結構性變化Stream。例如ArrayListdoc 說:
僅僅設置元素的值不是結構修改......
因此,在您的示例中,這意味著更改Employee本身不會更改List本身(不會刪除或添加元素)。但是改變List本身,將失敗ConcurrentModificationException:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.stream().forEach(x -> list.remove(x));
但是有些來源的干擾不僅僅是可以的,稱為弱一致遍歷,例如ConcurrentHashMap:
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()));
這不會失敗ConcurrentModificationException。
添加回答
舉報