W3docs

Come rimuovere i duplicati da una lista in Java

Rimuovi i duplicati da una lista Java con HashSet, LinkedHashSet o stream distinct.

Una List in Java ammette elementi duplicati per design, quindi quando hai bisogno che ogni valore appaia una sola volta devi rimuovere le ripetizioni tu stesso. Questo capitolo mostra i modi idiomatici per farlo, prestando attenzione al fatto che l'ordine di inserimento originale venga preservato o meno.

Usare un LinkedHashSet (ordine preservato)

L'approccio più pulito è copiare la lista in un insieme, poiché un Set rifiuta i duplicati automaticamente. Usa LinkedHashSet invece di un semplice HashSet in modo che l'ordine del primo elemento incontrato venga mantenuto:

List<String> unique = new ArrayList<>(new LinkedHashSet<>(list));

Avvolgere nuovamente l'insieme in un ArrayList restituisce una List, pronta per l'indicizzazione o per ulteriori elaborazioni. Il LinkedHashSet fa tutto il lavoro pesante: mentre viene riempito dalla lista originale, scarta silenziosamente qualsiasi elemento già visto, mentre la sua struttura collegata ricorda l'ordine in cui gli elementi sono arrivati per la prima volta.

Se non ti interessa l'ordine, un semplice HashSet è marginalmente più veloce e usa un po' meno memoria. Ma mescola l'ordine degli elementi, il che raramente è quello che vuoi quando visualizzi una lista, quindi LinkedHashSet è il default sicuro.

Usare la Stream API

Da Java 8 in poi, Stream.distinct() rimuove i duplicati in un'unica pipeline leggibile. Come LinkedHashSet, mantiene l'ordine di incontro degli elementi:

List<String> unique = list.stream()
        .distinct()
        .collect(Collectors.toList());

distinct() confronta gli elementi con equals() e hashCode(), esattamente come fa un insieme, quindi i tuoi oggetti devono implementare quei metodi correttamente per i tipi personalizzati. Questa forma eccelle quando la deduplicazione è un passaggio in una pipeline più grande — puoi concatenare filter, map o sorted intorno ad essa senza introdurre una collection temporanea.

Confronto degli approcci

Entrambe le tecniche comuni si basano su equals/hashCode e preservano entrambe l'ordine di inserimento; la differenza è principalmente di stile e contesto.

ApproccioOrdine mantenuto?Ideale quando
LinkedHashSetUn one-liner rapido e senza dipendenze
HashSetNoL'ordine non importa e la velocità è critica
stream().distinct()La deduplicazione fa parte di una pipeline stream più grande

Un punto chiave per tutti: costruiscono una nuova collection invece di mutare quella sorgente. Se devi deduplicare in-place, puoi invece svuotare la lista e re-aggiungere gli elementi univoci, oppure assegnare il risultato alla stessa variabile.

Esempio pratico

java— editable, runs on the server

Cosa osservare dall'esecuzione:

  • La lista originale mantiene tutti i 7 elementi, inclusi i ripetuti java e sql, perché una List ammette i duplicati.
  • Il risultato del LinkedHashSet ha solo 4 elementi — [java, sql, api, rest] — e appaiono nell'ordine del primo incontro, non ordinati o mescolati.
  • Il risultato di stream().distinct() è identico sia per dimensione che per ordine, confermando che le due tecniche sono intercambiabili in questo caso.
  • deduped.equals(viaStream) stampa true, poiché due liste sono uguali quando contengono gli stessi elementi nello stesso ordine.
  • La lista tags originale è invariata, quindi le operazioni di dedup hanno prodotto nuove liste senza mutare la sorgente.

Pratica

Pratica
Quale tipo di collection rimuove i duplicati preservando l'ordine di inserimento originale degli elementi?
Quale tipo di collection rimuove i duplicati preservando l'ordine di inserimento originale degli elementi?
Was this page helpful?