Esiste una implementazione di lista non duplicata là fuori?

So di SortedSet , ma nel mio caso ho bisogno di qualcosa che implementa List e non Set . Quindi c’è un’implementazione là fuori, nell’API o altrove?

Non dovrebbe essere difficile da implementare me stesso, ma ho pensato perché non chiedere prima la gente qui?

Non esiste una raccolta Java nella libreria standard per farlo. LinkedHashSet conserva l’ordinamento in modo simile a un List , quindi, quindi se avvolgi il tuo set in un List quando vuoi usarlo come List otterrai la semantica desiderata.

In alternativa, le collezioni Commons (o commons-collections4 , per la versione generica) hanno una List che fa già ciò che vuoi: SetUniqueList / SetUniqueList .

Quindi ecco cosa ho fatto alla fine. Spero che questo aiuti qualcun’altro.

 class NoDuplicatesList extends LinkedList { @Override public boolean add(E e) { if (this.contains(e)) { return false; } else { return super.add(e); } } @Override public boolean addAll(Collection collection) { Collection copy = new LinkedList(collection); copy.removeAll(this); return super.addAll(copy); } @Override public boolean addAll(int index, Collection collection) { Collection copy = new LinkedList(collection); copy.removeAll(this); return super.addAll(index, copy); } @Override public void add(int index, E element) { if (this.contains(element)) { return; } else { super.add(index, element); } } } 

Ecco cosa ho fatto e funziona.

Supponendo che io abbia una ArrayList per lavorare con la prima cosa che ho fatto è stata creata una nuova LinkedHashMap .

 LinkedHashSet hashSet = new LinkedHashSet() 

Quindi cerco di aggiungere il mio nuovo elemento a LinkedHashSet . Il metodo add non altera il LinkedHasSet e restituisce false se il nuovo elemento è un duplicato. Quindi questa diventa una condizione che posso testare prima di aggiungere a ArrayList .

 if (hashSet.add(E)) arrayList.add(E); 

Questo è un modo semplice ed elegante per evitare che i duplicati vengano aggiunti a un elenco di array. Se lo desideri puoi incapsularlo e sovrascrivere il metodo add in una class che estende ArrayList . Ricorda solo di occuparti di addAll looping degli elementi e chiamando il metodo add.

Dovresti prendere seriamente in considerazione la risposta di dhiller:

  1. Invece di preoccuparti di aggiungere i tuoi oggetti a un Elenco senza duplicati, aggiungili a un Set (qualsiasi implementazione), che per natura filtrerà i duplicati.
  2. Quando è necessario chiamare il metodo che richiede un elenco, inserirlo in un new ArrayList(set) (o una new LinkedList(set) , qualunque sia).

Penso che la soluzione che hai postato con NoDuplicatesList abbia alcuni problemi, principalmente con il metodo contains() , inoltre la tua class non gestisce il controllo dei duplicati nella Raccolta passati al tuo metodo addAll() .

Perché non incapsulare un set con una lista, ordina come:

 new ArrayList( new LinkedHashSet() ) 

Questo lascia l’altra implementazione per qualcuno che è un vero maestro delle collezioni 😉

Avevo bisogno di qualcosa del genere, quindi sono andato alle raccolte dei comuni e ho usato SetUniqueList, ma quando ho eseguito alcuni test delle prestazioni, ho scoperto che non sembra ottimizzato rispetto al caso se voglio usare un Set e ottenere un array usando il Metodo Set.toArray (), SetUniqueTest ha impiegato 20: 1 tempo per riempire e quindi attraversare 100.000 stringhe confrontandole con l’altra implementazione, il che è una grande differenza, quindi se ti preoccupi delle prestazioni, ti consiglio di usare il Set e ottieni una matrice invece di usare SetUniqueList, a meno che tu non abbia davvero bisogno della logica di SetUniqueList, allora devi controllare altre soluzioni …

Il metodo principale del codice di test:

public static void main (String [] args) {

 SetUniqueList pq = SetUniqueList.decorate(new ArrayList()); Set s = new TreeSet(); long t1 = 0L; long t2 = 0L; String t; t1 = System.nanoTime(); for (int i = 0; i < 200000; i++) { pq.add("a" + Math.random()); } while (!pq.isEmpty()) { t = (String) pq.remove(0); } t1 = System.nanoTime() - t1; t2 = System.nanoTime(); for (int i = 0; i < 200000; i++) { s.add("a" + Math.random()); } s.clear(); String[] d = (String[]) s.toArray(new String[0]); s.clear(); for (int i = 0; i < d.length; i++) { t = d[i]; } t2 = System.nanoTime() - t2; System.out.println((double)t1/1000/1000/1000); //seconds System.out.println((double)t2/1000/1000/1000); //seconds System.out.println(((double) t1) / t2); //comparing results 

}

Saluti Mohammed Sleem http://abusleem.net/blog

NOTA: non prende in considerazione l’implementazione di subList .

 import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; public class UniqueList extends ArrayList { private static final long serialVersionUID = 1L; /** Unique elements SET */ private final Set set=new HashSet(); /** Used by addAll methods */ private Collection addUnique(Collection col) { Collection unique=new ArrayList(); for(T e: col){ if (set.add(e)) unique.add(e); } return unique; } @Override public boolean add(T e) { return set.add(e) ? super.add(e) : false; } @Override public boolean addAll(Collection col) { return super.addAll(addUnique(col)); } @Override public void add(int index, T e) { if (set.add(e)) super.add(index, e); } @Override public boolean addAll(int index, Collection col) { return super.addAll(index, addUnique(col)); } } 

La documentazione per le interfacce di raccolta dice:

Set: una raccolta che non può contenere elementi duplicati.
Elenco: una raccolta ordinata (talvolta chiamata sequenza). Le liste possono contenere elementi duplicati.

Quindi, se non vuoi duplicati, probabilmente non dovresti usare una lista.

nel metodo add , perché non utilizzare HashSet.add() per controllare i duplicati invece di HashSet.consist() . HashSet.add() restituirà true se nessun duplicato e false altrimenti.

Fuori dalla mia testa, le liste permettono duplicati. È ansible implementare rapidamente un object UniqueArrayList e sovrascrivere tutte le funzioni di add / insert per verificare la presenza di contains() prima di chiamare i metodi ereditati. Per uso personale, è ansible implementare solo il metodo di add che si utilizza e ignorare gli altri per generare un’eccezione nel caso in cui i programmatori futuri tentassero di utilizzare l’elenco in un modo diverso.

Ho appena creato la mia UniqueList nella mia piccola libreria come questa:

 package com.bprog.collections;//my own little set of useful utilities and classs import java.util.HashSet; import java.util.ArrayList; import java.util.List; /** * * @author Jonathan */ public class UniqueList { private HashSet masterSet = new HashSet(); private ArrayList growableUniques; private Object[] returnable; public UniqueList() { growableUniques = new ArrayList(); } public UniqueList(int size) { growableUniques = new ArrayList(size); } public void add(Object thing) { if (!masterSet.contains(thing)) { masterSet.add(thing); growableUniques.add(thing); } } /** * Casts to an ArrayList of unique values * @return */ public List getList(){ return growableUniques; } public Object get(int index) { return growableUniques.get(index); } public Object[] toObjectArray() { int size = growableUniques.size(); returnable = new Object[size]; for (int i = 0; i < size; i++) { returnable[i] = growableUniques.get(i); } return returnable; } } 

Ho una class TestCollections che assomiglia a questo:

 package com.bprog.collections; import com.bprog.out.Out; /** * * @author Jonathan */ public class TestCollections { public static void main(String[] args){ UniqueList ul = new UniqueList(); ul.add("Test"); ul.add("Test"); ul.add("Not a copy"); ul.add("Test"); //should only contain two things Object[] content = ul.toObjectArray(); Out.pl("Array Content",content); } } 

Funziona bene. Tutto ciò che fa è aggiungere a un set se non ce l'ha già e c'è un Arraylist che è restituibile, così come un array di oggetti.