2012-04-16 40 views
12

Antes de publicar esta pregunta, encontré de alguna manera una pregunta similar publicada here. Pero la respuesta se basó en una cadena. Sin embargo, tengo una situación diferente aquí. No estoy tratando de eliminar String sino otro objeto llamado AwardYearSource. Esta clase tiene un atributo int llamado año. Por lo tanto, quiero eliminar duplicados según el año. es decir, si hay un año 2010 mencionado más de una vez, quiero eliminar ese objeto AwardYearSource. ¿Cómo puedo hacer eso?¿Cómo eliminar duplicados de una lista basada en un objeto java personalizado no un tipo primitivo?

+0

Java 8 maneras también es bastante agradable: http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC

Respuesta

45

La forma más sencilla de eliminar elementos en función de un campo es la siguiente (la preservación del orden):

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

Gracias. Solucionó mi problema. Sin embargo, cambié la primera línea de su código a Map map = new LinkedHashMap (); .... de lo contrario no compilará. – WowBow

+5

Lo sentimos, la sintaxis '<>' solo funciona en Java 7. –

+0

Buen truco. Gracias resolver mi problema. – James

0

Se puede usar un mapa y almacenar sus objetos con el año como clave:

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

etc. 

al final el mapa contendrá valores únicos por año, lo que se puede llamar con el método de valores:

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

Cree un objeto HashMap con int como tipo de clave y su clase como tipo de valor. Entonces iterar sobre la lista e insertar cada elemento al mapa usando:

mymap.put(source.year, source); 

entonces retirar todos los elementos de la lista origianl y iterar sobre el mapa e insertar cada elemento a la lista.

+0

¿De verdad? ¿Podrías dar más detalles? Aunque al menos uno de los iteradores es innecesario, consulte algunas de las otras respuestas. Y esto tendría algunos efectos secundarios desagradables, si se usa en un contexto enhebrado. –

+0

¿Quizás has publicado este comentario en la respuesta incorrecta? No veo ningún iterador en mis soluciones y es bastante seguro. – smichak

+0

Menciona explícitamente iterar, y va a utilizar al menos un iterador _implicit_ (compilador generado, en el caso de la construcción de cada uno). Si esto se está empaquetando en su propio método (que debería ser), eliminar elementos de la lista original es ** absolutamente NO ** seguro para los hilos. –

1

Otra forma sería anular hashCode() y equals(Object obj) para su objeto. Como solo tiene un campo que desea usar para determinar la igualdad, esto es bastante sencillo. Algo así como:

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; 
} 

continuación, sólo puede pegar todos los objetos en una Set para eliminar duplicados:

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

Si las sustituciones de clase AwardYearSource métodos equals y hashCode (Eclipse pueden generar ambos), entonces puedes agregarlos a un Set. El conjunto no contendrá ningún duplicado.

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); 
    } 
} 

La salida es [2000]. Solo un artículo en el conjunto.

1

Bastante simple. Aunque algo me molesta acerca de las versiones del mapa (no es que dude de que funcionen, de alguna manera parece una exageración, aunque esta versión no es necesariamente mejor en ese sentido).
La respuesta es funcional y enhebrable (suponiendo que AwardYearSource es inmutable).

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

Demasiadas finales –

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

Esto debería ayudar en donde, la duplicación se decide sobre la base de ciertos bienes (o combinación de propiedades), año en este caso. Espero que esto ayude.

Cuestiones relacionadas