从 ConcurrentLinkedQueue 迭代和删除元素
Iterating and removing elements from ConcurrentLinkedQueue
我定义了一个 ConcurrentLinkedQueue 并像这样循环它:
ConcurrentLinkedQueue clq
.forEach((carTask -> {
现在,如果我从队列中删除 carTask。这是一个元素
在我们执行 forEach 时在队列中会导致任何问题吗?
我想到的一个替代方案是将要删除的元素放入
在一个单独的列表中,一旦 forEach 结束,只需删除所有
列表中队列中的元素。
我不确定这种替代方法是否完美
有什么建议或更好的方法来解决这个问题吗?
此特定示例不会导致错误,因为 Queue
的此实现允许并发修改。
但是 通过 remove
方法从 Java 集合中删除元素,当您遍历元素时,通常会导致 ConcurrentModificationException
。相反,使用 Iterator
并调用其 remove
方法是一个好习惯:
Collection<String> c = new LinkedList<>();
c.add("foo");
c.add("bar");
for(Iterator<String> it = c.iterator(); it.hasNext(); ) {
String s = it.next();
if(s.equals("foo")) {
it.remove();
}
}
// collection now contains only "bar"
除了防止ConcurrentModificationException
,这是更可取的,因为remove
对于很多集合的时间复杂度是线性。由于这个队列是作为链表实现的,所以必须遍历链表,直到找到要移除的元素。使用 Iterator
,您已经找到了该元素,并且可以将其“就地”移除。
如果找到要删除的元素,并且它是队列中的最后一个元素怎么办?对该项目调用 remove
需要一直遍历到队列的末尾 再次 。此外,它需要为前面的每个元素调用 equals
。您绝对不想将要删除的项目放入列表中,因为您将具有相同的负面性能特征(以及另一个 List
的分配)。
我定义了一个 ConcurrentLinkedQueue 并像这样循环它:
ConcurrentLinkedQueue clq
.forEach((carTask -> {
现在,如果我从队列中删除 carTask。这是一个元素
在我们执行 forEach 时在队列中会导致任何问题吗?
我想到的一个替代方案是将要删除的元素放入
在一个单独的列表中,一旦 forEach 结束,只需删除所有
列表中队列中的元素。
我不确定这种替代方法是否完美
有什么建议或更好的方法来解决这个问题吗?
此特定示例不会导致错误,因为 Queue
的此实现允许并发修改。
但是 通过 remove
方法从 Java 集合中删除元素,当您遍历元素时,通常会导致 ConcurrentModificationException
。相反,使用 Iterator
并调用其 remove
方法是一个好习惯:
Collection<String> c = new LinkedList<>();
c.add("foo");
c.add("bar");
for(Iterator<String> it = c.iterator(); it.hasNext(); ) {
String s = it.next();
if(s.equals("foo")) {
it.remove();
}
}
// collection now contains only "bar"
除了防止ConcurrentModificationException
,这是更可取的,因为remove
对于很多集合的时间复杂度是线性。由于这个队列是作为链表实现的,所以必须遍历链表,直到找到要移除的元素。使用 Iterator
,您已经找到了该元素,并且可以将其“就地”移除。
如果找到要删除的元素,并且它是队列中的最后一个元素怎么办?对该项目调用 remove
需要一直遍历到队列的末尾 再次 。此外,它需要为前面的每个元素调用 equals
。您绝对不想将要删除的项目放入列表中,因为您将具有相同的负面性能特征(以及另一个 List
的分配)。