tl; dr:
mantenerlo semplice. Utilizzare
list.removeAll(new HashSet<T>(listOfElementsToRemove));
invece.
Come Eran già menzionato nel his answer: Il basso rendimento deriva dal fatto che la pseudocodice di un generico removeAll
implementazione è
public boolean removeAll(Collection<?> c) {
for (each element e of this) {
if (c.contains(e)) {
this.remove(e);
}
}
}
Quindi la chiamata contains
che viene fatto nella lista dei gli elementi da rimuovere causano la prestazione O (n * k) (dove n
è il numero di elementi da rimuovere e è il numero di elementi nell'elenco in cui viene chiamato il metodo).
Ingenuamente, si potrebbe immaginare che la chiamata this.remove(e)
su un List
potrebbe anche avere O (k), e questa implementazione avrebbe anche complessità quadratica. Ma questo non è il caso: hai detto che gli elenchi sono specificatamente ArrayList
istanze. E il metodo ArrayList#removeAll
è implementato per delegare a un metodo chiamato batchRemove
che opera direttamente sull'array sottostante e fa non rimuovere gli elementi singolarmente.
Quindi tutto quello che dovete fare è assicurarsi che la ricerca nella collezione che contiene gli elementi da rimuovere sia veloce - preferibilmente O (1). Questo può essere ottenuto inserendo questi elementi in un Set
. Alla fine, si può semplicemente essere scritto come
list.removeAll(new HashSet<T>(listOfElementsToRemove));
note collaterali:
La risposta di Eran ha IMHO due grossi inconvenienti: Prima di tutto, richiede ordinamento le liste, che è O (n * logn) - e semplicemente non è necessario. Ma ancora più importante (e ovviamente): L'ordinamento probabilmente cambierà l'ordine degli elementi! Cosa succede se questo non è semplicemente desiderato?
In remoto: ci sono altre sottigliezze coinvolte nelle implementazioni removeAll
. Ad esempio, HashSet removeAll method is surprisingly slow in alcuni casi. Anche se questo si riduce anche alla O (n * n) quando gli elementi da rimuovere sono memorizzati in una lista, il comportamento esatto può davvero essere sorprendente in questo caso particolare.
Crea tempList2 come HashSet e probabilmente vedrai un notevole aumento delle prestazioni. –
hai considerato prima l'ordinamento di entrambi gli elenchi e quindi semplicemente il iterazione del primo (quello da cui rimuovi gli elementi)? Modifica: in sostanza ciò che @Eran ha proposto di seguito. – ingenious
Correlati: * [Insight in Collections removeAll method] (http://stackoverflow.com/questions/33227592/insight-into-collections-removeall-method) * – DaoWen