2010-09-24 5 views

Respuesta

17

Tenga una mirada en LinkedHashSet

+1

LinkedHashSet es una implementación de la interfaz Set ... ¿Por qué recomienda esta en lugar de otra? – pgras

+5

@pgras, tal vez porque el orden en que se agregan los elementos se mantiene intacto, solo como una lista. –

+2

@ Wolfgang, @Bart K: el problema es que LinkedHashSet NO es una Lista. Implementa Set API y no le permite obtener, actualizar o insertar o eliminar elementos de forma posicional. –

15

Un conjunto eliminará automáticamente los duplicados, pero es una Colección en lugar de una Lista.

No creo que haya una lista que elimine los duplicados en la biblioteca estándar.

La página Annotated Outline of the Collections Framework de la documentación de la API de Java 6 SE dice que "los duplicados están generalmente permitidos".

+1

+1 Para señalar la diferencia entre Sets y Lits. –

5

Si desea eliminar duplicados, utilice Set

3

desea utilizar un juego tal vez, por ejemplo, HashSet(), en lugar de una lista? Ninguna lista eliminará los duplicados, por definición, las listas lo permiten.

4

Al igual que el cartel mencionado anteriormente, no hay una lista con manejo exclusivo.

Mira List (Java Platform SE 6)

A diferencia de conjuntos, listas suelen permitir que los elementos duplicados. Más formalmente, las listas generalmente permiten pares de elementos e1 y e2 tales que e1.equals (e2), y normalmente permiten múltiples elementos nulos si permiten elementos nulos en absoluto. No es inconcebible que alguien desee implementar una lista que prohíba los duplicados, lanzando excepciones de tiempo de ejecución cuando el usuario intenta insertarlos, pero esperamos que este uso sea raro.

+0

Rara ... y costoso. Lanzar excepciones es costoso. –

+0

caro, cierto. Pero a veces inevitable. muchos métodos de recolección lanzan UnsupportedOperationException y no hay forma de que el código del cliente descubra que lo hacen de antemano. RuntimeExceptions es algo con lo que debes lidiar en el marco de colecciones. –

4

Puede ampliar el existente java.util.ArrayList y encapsular un java.util.Set en él. Debe reemplazar todos los métodos add(...), addAll(...) y remove y primera verificación si un elemento está en el conjunto encapsulado (en el caso de añadir a la lista):

public class ListSet<E> extends ArrayList<E> { 

    private Set<E> set; 

    public ListSet() { 
     set = new HashSet<E>(); 
    } 

    @Override 
    public boolean add(E element) { 
     if(set.add(element)) { 
      super.add(element); 
      return true; 
     } 
     return false; 
    } 

    // other add and remove methods 
} 

EDITAR

Como se mencionó @Alnitak: no olvide sincronizar su HashSet de respaldo cada vez que se elimine un elemento.

+1

Me gusta esto, y es cómo lo habría hecho. Esto mantiene específicamente toda la semántica de una lista, mientras aplica la restricción de no duplicados (aunque a costa de algo de memoria). PD. no olvides sincronizar tu HashSet de respaldo cada vez que se elimine un elemento ... – Alnitak

+0

Estaba pensando en hacer algo muy similar, pero estoy pendiente de que implementes la implementación de agregar (indexar, E). Me imagino que si encuentras un duplicado de E en los datos, entonces fallas al insertar en la posición. La interfaz List para add (index, E) devuelve el vacío, por lo que no puede informar de esta condición fallida. –

0

Aquí es una extensión de ArrayList que rechaza duplicados:

public class NoDupeList<E> extends ArrayList<E>{ 

    private static final long serialVersionUID = -2682691450003022201L; 

    public NoDupeList(){ 
     super(); 
    } 

    public NoDupeList(final Collection<? extends E> c){ 
     super(c instanceof Set<?> ? c : new LinkedHashSet<E>(c)); 
    } 

    public NoDupeList(final int initialCapacity){ 
     super(initialCapacity); 
    } 

    @Override 
    public boolean add(final E e){ 
     return !this.contains(e) && super.add(e); 
    }; 

    @Override 
    public boolean addAll(final Collection<? extends E> c){ 
     final List<E> intermediate = new ArrayList<E>(c); 
     intermediate.removeAll(this); 
     return super.addAll(intermediate); 
    } 

    @Override 
    public void add(final int index, final E element){ 
     if(!this.contains(element)){ 
      super.add(index, element); 
     } 
    }; 

    @Override 
    public E set(final int index, final E element){ 
     if(this.contains(element) && !this.get(index).equals(element)){ 
      throw new IllegalArgumentException("This would cause a duplicate"); 
     } 
     return super.set(index, element); 
    }; 

} 

La única cosa que no puedo tratar es el método set(). Mi solución es arrojar un IllegalArgumentException si eso causaría un duplicado, pero quizás uno generalmente debería dejar que este método arroje un UnsupportedOperationException.

De todos modos, aquí está un método de prueba:

@Test 
public void testNoDupeList() throws Exception{ 
    final List<String> list = 
     new NoDupeList<String>(Arrays.asList("abc", "def", "abc")); 
    assertEquals(list, Arrays.asList("abc", "def")); 
    list.addAll(Arrays.asList("abc", "def", "ghi")); 
    assertEquals(list, Arrays.asList("abc", "def", "ghi")); 
    try{ 
     list.set(2, "abc"); 
     fail("This should have caused an Exception"); 
    } catch(final Exception e){} 
}; 
2

no lo hace, como alguien sugirió, poner en práctica su propia lista que duplicar cheque y devuelve false si no es un duplicado en add().

¿Por qué?Dado que va a romper el contrato interfaz List, que dice:

public boolean add(E e) 
[...] 
Returns: 
     true (as specified by Collections.add()) 

List.add (E e) debe devolver verdadero y añadir el elemento a la lista, o lanzar una excepción. Las listas no están destinadas a tener comprobaciones duplicadas, para eso sirven los Conjuntos.

0

La forma más fácil de obtener una real List que está ordenada y no tiene duplicados serían para envolver así:

List<Integer> unique = 
    new ArrayList<Integer>(new TreeSet<Integer>(Arrays.asList(1, 1, 2, 2, 3, 3))); 

Tenga en cuenta que cuando se agrega a esta lista los duplicados se no ser eliminados, aunque , pero tal vez esto funcione para ti.

1

En ese momento puede hacer su propia clase y @Override agregar método a su clase. "solo vea mi código y practíquelo"

import java.util.ArrayList; 

import java.util.List; 

class MyList extends ArrayList<Integer> { 

    private static final long serialVersionUID = 1L; 

    @Override 
    public boolean add(Integer element) { 

     if (!found(element)) { 
      super.add(element); 
     } 
     return false; 

    } 
    public boolean found(Integer e) { 
     return equals(e); 
    } 
    public boolean equals(Integer e) { 

     for (int i = 0; i < super.size(); i++) { 
      if (super.get(i).equals(e)) 
       return true; 
     } 

     return false; 
    } 

} 

public class ListRemovingDuplicated { 

    public static void main(String[] abd) { 

     List<Integer> obj = new MyList(); 
     obj.add(10); 
     obj.add(20); 
     obj.add(10); 
     obj.add(10); 
     obj.add(30); 
     System.out.println(obj); 

    } 
} 
Cuestiones relacionadas