In realtà, dipende dalla versione di jdk che si sta utilizzando. In JDK6, la maggior parte della classe di raccolta ereditano il metodo removeAll dalla classe AbstractCollection:
public boolean removeAll(Collection<?> c) {
boolean modified = false;
Iterator<?> e = iterator();
while (e.hasNext()) {
if (c.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
}
Quindi, in un certo scenario, questo causerà una CME (ConcurrentModificationException
), ad esempio:
ArrayList<Integer> it = new ArrayList<Integer>();
it.add(1);
it.add(2);
it.add(3);
List<Integer> sub = it.subList(0,5);
it.removeAll(sub);
tuttavia
, in jdk8, la maggior parte delle raccolte ha la propria implementazione removeAll, come ArrayList. La classe ArrayList ha il proprio metodo removeAll, che chiamare un metodo batchRemove privato:
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
Questa utilizzando ciclo for iterate sopra la matrice sottostante, e cambiando la variabile modCount sola volta dopo la fine di tale metodo, durante l'iterazione della sottolista (invocando da c.taintains (elementData [r])), la mod modCount non cambia, quindi non verrà generata alcuna CME.
fonte
2016-08-11 15:31:27
Quale possibile motivo avresti per farlo invece di 'ops.clear()'? –
Sì, può; si itera sulla stessa collezione da cui si rimuove, questo può portare a una 'ConcurrentModificationException'. – fge
Si prega di vedere la mia modifica. – isoman