2010-09-24 3 views

Répondre

17

Jetez un oeil à LinkedHashSet

+1

LinkedHashSet est une implémentation de l'interface Set ... Pourquoi recommandez-vous celui-ci plutôt qu'un autre? – pgras

+5

@pgras, peut-être parce que l'ordre dans lequel les éléments sont ajoutés est gardé intact, tout comme une liste. –

+2

@Wolfgang, @Bart K - le problème est que LinkedHashSet n'est PAS une liste. Il implémente l'API Set et ne vous permet pas d'obtenir, mettre à jour ou insérer ou supprimer des éléments positionnellement. –

15

Un ensemble éliminera automatiquement les doublons, mais il est une collection plutôt qu'une liste.

Je ne pense pas qu'il existe une liste qui élimine les doublons dans la bibliothèque standard.

La page Annotated Outline of the Collections Framework de la documentation de l'API Java 6 SE indique que «les doublons sont généralement autorisés».

+1

+1 Pour indiquer la différence entre Ensembles et Lits. –

5

Si vous voulez éliminer les doublons, utilisez Set

3

Vous voulez un jeu peut-être, par exemple HashSet(), plutôt qu'une liste? Aucune liste n'éliminera les doublons, par définition les listes les autorisent.

4

Comme l'affiche ci-dessus a dit, il n'y a pas de liste avec manipulation unique.

Regardez List (Java Platform SE 6)

Contrairement aux jeux, listes permettent généralement des éléments en double. Plus formellement, les listes autorisent généralement des paires d'éléments e1 et e2 telles que e1.equals (e2), et elles autorisent généralement plusieurs éléments NULL s'ils permettent des éléments null du tout. Il n'est pas inconcevable que quelqu'un veuille implémenter une liste qui interdit les doublons, en lançant des exceptions d'exécution lorsque l'utilisateur tente de les insérer, mais nous nous attendons à ce que cette utilisation soit rare.

+0

Rare ... et coûteux. Lancer des exceptions est cher. –

+0

cher, vrai. Mais parfois inévitable. De nombreuses méthodes de collecte lancent UnsupportedOperationException et le code client n'a aucun moyen de savoir si elles le font à l'avance. RuntimeExceptions est quelque chose que vous avez à faire dans le cadre des collections. –

4

Vous pouvez étendre le java.util.ArrayList existant et y encapsuler un java.util.Set. Vous devez passer outre tous add(...), addAll(...) et remove méthodes et d'abord vérifier si un élément est dans l'ensemble encapsulé (dans le cas de l'ajouter à la liste):

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 
} 

EDIT

Comme mentionné @Alnitak: n'oubliez pas de synchroniser votre HashSet de sauvegarde chaque fois qu'un élément est supprimé.

+1

J'aime ça, et c'est comme ça que je l'aurais fait. Ceci maintient spécifiquement toute la sémantique d'une liste, tout en appliquant la contrainte de non-duplication (bien qu'au prix d'un peu de mémoire). p.s. n'oubliez pas de synchroniser votre HashSet backing chaque fois qu'un élément est supprimé ... – Alnitak

+0

Je pensais à faire quelque chose de très similaire, mais je suis accroché sur vous implémenterait l'implémentation add (index, E). J'imagine que si vous trouvez une copie de E dans les données, alors vous n'insérez pas à la position. L'interface List pour add (index, E) renvoie void, de sorte que vous ne pouvez pas signaler cette condition échouée. –

0

Voici une extension de ArrayList qui rejette les doublons:

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 seule chose que je ne peux pas traiter est la méthode set(). Ma solution est de lancer un IllegalArgumentException si cela provoque un doublon, mais peut-être que l'on devrait généralement laisser cette méthode lancer un UnsupportedOperationException à la place.

Quoi qu'il en soit, voici une méthode d'essai:

@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

Ne pas, comme quelqu'un a suggéré, mettre en œuvre votre propre liste qui fait de doublons et retourne false s'il y a un double à ajouter().

Pourquoi?Parce que vous brisera le contrat d'interface List qui dit:

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

List.add (E e) DOIT retourner true et ajoutez l'élément à la liste, ou lancer une exception. Les listes ne sont pas censées avoir des vérifications en double, c'est ce que les ensembles sont pour.

0

La meilleure façon d'obtenir une List réelle qui est triée et n'a pas de doublons serait de l'envelopper comme ceci:

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

Notez que lorsque vous ajoutez à cette doublons liste ne pas être éliminés si , mais peut-être que cela fonctionne pour vous.

1

Au moment où vous pouvez créer votre propre classe et @Override ajouter une méthode à votre classe. "juste voir mon code et pratiquez-le"

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

    } 
} 
Questions connexes