2012-04-16 9 views
12

Prima di pubblicare questa domanda, ho trovato in qualche modo una domanda simile pubblicata here. Ma la risposta era basata su una stringa. Tuttavia, ho una situazione diversa qui. Non sto cercando di rimuovere String ma un altro oggetto chiamato AwardYearSource. Questa classe ha un attributo int chiamato anno. Quindi voglio rimuovere i duplicati in base all'anno. se c'è l'anno 2010 menzionato più di una volta, voglio rimuovere quell'oggetto AwardYearSource. Come lo posso fare?Come rimuovere i duplicati da un elenco basato su un oggetto java personalizzato e non su un tipo primitivo?

+0

Java 8 way è anche molto carino: http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC

risposta

45

Il modo più semplice per rimuovere gli elementi in base a un campo è la seguente (ordine preservando):

Map<Integer, AwardYearSource> map = new LinkedHashMap<>(); 
for (AwardYearSource ays : list) { 
    map.put(ays.getYear(), ays); 
} 
list.clear(); 
list.addAll(map.values()); 
+1

Grazie. Ha risolto il mio problema. Comunque ho cambiato la prima riga del tuo codice in Map map = new LinkedHashMap (); .... altrimenti non verrà compilato. – WowBow

+5

Siamo spiacenti, la sintassi '<>' funziona solo in Java 7. –

+0

Bel trucco. Grazie, risolvi il mio problema – James

0

Si potrebbe utilizzare una mappa e memorizzare gli oggetti con l'anno come chiave:

Map<Integer, AwardYearSource> map = new HashMap<Integer, AwardYearSource>(); 
map.put(someAwardYearSource1.getYear(), someAwardYearSource1); 
map.put(someAwardYearSource2.getYear(), someAwardYearSource2); 

etc. 

alla fine la mappa conterrà valori unici per anno, che è possibile chiamare il metodo valori:

Collection<AwardYearSource> noDups = map.values(); 
0

Creare un oggetto HashMap con int come tipo di chiave e la classe come tipo di valore. Poi iterare nella lista e inserire ogni elemento della mappa utilizzando:

mymap.put(source.year, source); 

quindi rimuovere tutti gli elementi dalla lista origianl e iterare la mappa e inserire ogni elemento alla lista.

+0

Davvero? Potresti fornire maggiori dettagli? Sebbene almeno uno degli iteratori non sia necessario, vedere alcune delle altre risposte. E questo avrebbe alcuni effetti collaterali sgradevoli, se usati in un contesto filettato. –

+0

Forse hai postato questo commento sulla risposta sbagliata? Non vedo alcun iteratore nelle mie soluzioni ed è abbastanza sicuro. – smichak

+0

Si menziona esplicitamente iterate e si utilizzerà almeno un iteratore _implicit_ (compilatore generato, nel caso del costrutto for-each). Se questo viene impacchettato nel proprio metodo (quale dovrebbe essere), quindi rimuovere gli elementi dall'elenco originale è ** assolutamente NON ** threadsafe. –

1

Un altro modo sarebbe quello di ignorare hashCode() e equals(Object obj) per il proprio oggetto. Dato che ha solo un campo che vuoi usare per determinare l'uguaglianza, questo è abbastanza semplice. Qualcosa di simile:

public boolean equals(Object obj) { 
    if (obj == null || !(obj instanceof AwardYearSource)) { 
    return false; 
    } 
    return (this.year == ((AwardYearSource)obj).year); 
} 
public int hashCode() { 
    return this.year; 
} 

allora si può solo attaccare tutti gli oggetti in un Set per rimuovere i duplicati:

Set<AwardYearSource> set = new Set<AwardYearSource>(); 

set.add(new AwardYearSource(2011)); 
set.add(new AwardYearSource(2012)); 
set.add(new AwardYearSource(2011)); 

for (AwardYearSource aws : set) { 
    System.out.println(aws.year); 
} 
0

Se le sostituzioni di classe AwardYearSource uguale e metodi hashCode (Eclipse possono generare entrambi), poi puoi aggiungerli a un Set. Il Set non conterrà duplicati.

public class AwardYearSource 
{ 
    private final int year; 

    public AwardYearSource(int year) 
    { 
     this.year = year; 
    } 

    @Override 
    public int hashCode() 
    { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + year; 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     AwardYearSource other = (AwardYearSource) obj; 
     if (year != other.year) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() 
    { 
     return String.valueOf(year); 
    } 


    public static void main(String[] args) 
    { 
     Set<AwardYearSource> set = new HashSet<AwardYearSource>(); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 

     System.out.println(set); 
    } 
} 

L'uscita è [2000]. Solo un oggetto nel set.

1

Abbastanza semplicemente. Anche se qualcosa mi infastidisce sulle versioni delle mappe (non che dubito che funzionerebbero, sembra un po 'eccessivo, in qualche modo - sebbene questa versione non sia necessariamente migliore a tale riguardo).
La risposta è funzionale e thread-safe (supponendo che AwardYearSource sia immutabile).

public static List<AwardYearSource> removeDuplicateYears(
              final Collection<AwardYearSource> awards) { 
    final ArrayList<AwardYearSource> input = new ArrayList<AwardYearSource>(awards); 
    // If there's only one element (or none), guaranteed unique. 
    if (input.size() <= 1) { 
     return input; 
    } 
    final HashSet<Integer> years = new HashSet<Integer>(input.size(), 1); 
    final Iterator<AwardYearSource> iter = input.iterator(); 
    while(iter.hasNext()) { 
     final AwardYearSource award = iter.next(); 
     final Integer year = award.getYear(); 
     if (years.contains(year)) { 
      iter.remove(); 
     } else { 
      years.add(year); 
     } 
    } 
    return input;  

} 
+0

Troppe finali –

0
Set<Integer> set = new HashSet<>(); 
list.removeIf(i -> set.contains(i.getYear()) ? true : !set.add(i.getYear())); 

Questo dovrebbe aiutare in cui, la duplicazione è deciso sulla base di alcuni beni (o combinazione di proprietà), anno in questo caso. Spero che questo ti aiuti.

Problemi correlati