如果您正在寻找“足够快”的解决方案,可以使用ConcurrentLinkedQueue.其Iterator.remove()中众所周知的内存泄漏问题已修复为http://bugs.java.com/view_bug.do?bug_id=6785442的一部分.现在已删除ConcurrentLinkedQueue $Node应成功GC.但如果您正在寻找性能最佳的解决方案,那么……
>根本不要使用迭代器(因此也可以使用for),因为Collection.iterator()准备Iterator的新实例,顺便说一下,它的next()方法不是免费的:)每次当你使用Iterator迭代一个集合,你至少花费CPU时间:大约10条指令为新对象分配内存构造函数的指令(参见ConcurrentLinkedQueue $Itr的来源)ConcurrentLinkedQueue $Itr.next()从Eden中删除对象在小型GC上.
>普通数组直接索引是最快的迭代技术.因此,使用CopyOnWriteArrayList或实现您自己的集合来使用普通数组迭代许多项.例如,如果您很少添加/删除项目,并且您希望在迭代时删除它们而不是按索引删除它们,则可以尝试类似以下内容:
public enum IterationResult {
NEXT, REMOVE, BREAK;
}
public interface CollectionIterator {
IterationResult onObject(T object);
}
public interface CollectionModification {
CollectionModification add(T item);
CollectionModification remove(T item);
}
public class MyCollection {
private volatile State state;
private final ReentrantLock modificationLock = new ReentrantLock();
private State currentModification;
public MyCollection() {
this(10);
}
public MyCollection(int initialSize) {
state = new State(initialSize);
}
public CollectionModification startModification() {
modificationLock.lock();
currentModification = new State(state);
return currentModification;
}
public void finishModification() {
state = currentModification;
modificationLock.unlock();
}
@SuppressWarnings("unchecked")
public void iterate(CollectionIterator it) {
final State currentState = state;
State modifiedState = null;
try {
out_:
for (int i = 0; i < currentState.size; i++) {
final T item = (T) currentState.items[i]; // unchecked
final IterationResult result = it.onObject(item);
switch (result) {
case BREAK:
break out_;
case REMOVE:
if (modifiedState == null) {
modifiedState = (State) startModification();
}
modifiedState.removeExactly(item);
break;
default:
break;
}
}
} finally {
if (modifiedState != null) {
finishModification();
}
}
}
private class State implements CollectionModification {
private Object[] items;
private int size;
private State(int initialSize) {
items = new Object[initialSize];
}
private State(State from) {
items = new Object[from.items.length];
size = from.size;
System.arraycopy(from.items, 0, items, 0, size);
}
@Override
public CollectionModification add(T item) {
if (size == items.length) {
final Object[] newItems = new Object[size + size >>> 1];
System.arraycopy(items, 0, newItems, 0, size);
items = newItems;
}
items[size] = item;
size++;
return this;
}
@Override
public CollectionModification remove(T item) {
for (int i = 0; i < size; i++) {
if (Objects.equals(item, items[i])) {
removeItem(i);
break;
}
}
return this;
}
private void removeExactly(T item) {
for (int i = 0; i < size; i++) {
if (item == items[i]) {
removeItem(i);
break;
}
}
}
private void removeItem(int index) {
if (index < items.length - 1) {
System.arraycopy(items, index + 1, items, index, size - 1);
}
size--;
}
}
}
用法:
CollectionIterator remove2 = new CollectionIterator() {
@Override
public IterationResult onObject(Integer object) {
return object == 2 ? IterationResult.REMOVE : IterationResult.NEXT;
}
};
MyCollection col = new MyCollection<>();
CollectionModification mod = col.startModification();
try {
mod.add(new Integer(1))
.add(new Integer(2))
.add(new Integer(3));
} finally {
col.finishModification();
}
col.iterate(remove2);
这与CopyOnWriteArrayList非常相似.顺便说一句,如果你只有一个修改集合的线程(单个编写器)和许多读者,你就可以摆脱锁定,因为volatile足以保证作者和所有读者之间所有变化的可见性.此外,如果延迟对您很重要,您可以通过忙等待替换经典锁定以获得无锁定收集.
您应该了解的主要内容是,在许多情况下,针对特定要求的最高性能解决方案是编写一段您自己的微调代码.这是不付你没用的东西的方法.这就是为什么高性能/低延迟应用程序通常不会在其主要路径中使用常见的第三方库