Je sais à propos de SortedSet
, mais dans mon cas, j'ai besoin de quelque chose qui implémente List
, et non pas Set
. Alors, y a-t-il une implémentation disponible, dans l'API ou ailleurs?
Cela ne devrait pas être difficile à mettre en œuvre moi-même, mais je me suis dit pourquoi ne pas demander d'abord aux gens ici?
Il n'y a pas de collection Java dans la bibliothèque standard pour ce faire. LinkedHashSet<E>
conserve l'ordre similaire à un List
, donc si vous enveloppez votre ensemble dans un List
lorsque vous souhaitez l'utiliser comme List
, vous Obtenez la sémantique que vous voulez.
Alternativement, le Commons Collections (ou commons-collections4
, pour la version générique) a un List
qui fait ce que vous voulez déjà: SetUniqueList
/ SetUniqueList<E>
.
Voici ce que j'ai fait et ça marche.
En supposant que j'ai un ArrayList
pour travailler avec la première chose que j'ai faite a été créée un nouveau LinkedHashMap
.
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
Ensuite, j'essaie d'ajouter mon nouvel élément au LinkedHashSet
. La méthode add ne modifie pas le LinkedHasSet
et renvoie false si le nouvel élément est un doublon. Donc, cela devient une condition que je peux tester avant d’ajouter à la ArrayList
.
if (hashSet.add(E)) arrayList.add(E);
C'est un moyen simple et élégant d'éviter que des doublons ne soient ajoutés à une liste de tableaux. Si vous le souhaitez, vous pouvez l'encapsuler et remplacer la méthode add dans une classe qui étend le ArrayList
. Rappelez-vous simplement de traiter addAll
en parcourant les éléments et en appelant la méthode add.
Alors voici ce que j'ai finalement fait. J'espère que ça aidera quelqu'un d'autre.
class NoDuplicatesList<E> extends LinkedList<E> {
@Override
public boolean add(E e) {
if (this.contains(e)) {
return false;
}
else {
return super.add(e);
}
}
@Override
public boolean addAll(Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(copy);
}
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(index, copy);
}
@Override
public void add(int index, E element) {
if (this.contains(element)) {
return;
}
else {
super.add(index, element);
}
}
}
Vous devriez sérieusement considérer la réponse de Dhiller:
new ArrayList(set)
(ou dans un new LinkedList(set)
, peu importe).Je pense que la solution que vous avez publiée avec NoDuplicatesList
présente quelques problèmes, principalement avec la méthode contains()
. De plus, votre classe ne gère pas la recherche de doublons dans la collection transmise à votre fonction addAll()
méthode.
Pourquoi ne pas encapsuler un ensemble avec une liste, trier comme suit:
new ArrayList( new LinkedHashSet() )
Cela laisse l’autre implémentation à quelqu'un qui est un vrai maître des collections ;-)
J'avais besoin de quelque chose comme ça, alors je suis allé dans les collections communes et j'utilisais SetUniqueList, mais quand j'ai lancé un test de performance, j'ai constaté qu'il ne semblait pas être optimisé par rapport à la casse si je souhaitais utiliser un ensemble et obtenir un tableau à l'aide du. Set.toArray (), le SetUniqueTest a mis 20: 1 à remplir, puis parcourir 100 000 chaînes en comparant avec l’implémentation implémentée, ce qui représente une différence considérable. Par conséquent, si vous vous inquiétez des performances, je vous recommande d’utiliser obtenez un tableau au lieu d'utiliser SetUniqueList, sauf si vous avez vraiment besoin de la logique de SetUniqueList, alors vous devez vérifier d'autres solutions ...
La méthode principale du code de test:
public static void main (String [] args) {
SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();
long t1 = 0L;
long t2 = 0L;
String t;
t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;
t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
s.add("a" + Math.random());
}
s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
t = d[i];
}
t2 = System.nanoTime() - t2;
System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2); //comparing results
}
Cordialement Mohammed Sleem http://abusleem.net/blog
NOTE: cela ne prend pas subList implémentation en compte.
import Java.util.ArrayList;
import Java.util.Collection;
import Java.util.HashSet;
import Java.util.Set;
public class UniqueList<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
/** Unique elements SET */
private final Set<T> set=new HashSet();
/** Used by addAll methods */
private Collection<T> addUnique(Collection<? extends T> col) {
Collection<T> unique=new ArrayList();
for(T e: col){
if (set.add(e)) unique.add(e);
}
return unique;
}
@Override
public boolean add(T e) {
return set.add(e) ? super.add(e) : false;
}
@Override
public boolean addAll(Collection<? extends T> col) {
return super.addAll(addUnique(col));
}
@Override
public void add(int index, T e) {
if (set.add(e)) super.add(index, e);
}
@Override
public boolean addAll(int index, Collection<? extends T> col) {
return super.addAll(index, addUnique(col));
}
}
Le documentation pour les interfaces de collection dit:
Set - une collection qui ne peut pas contenir d'éléments en double.
Liste - une collection ordonnée (parfois appelée séquence). Les listes peuvent contenir des éléments en double.
Donc, si vous ne voulez pas de doublons, vous ne devriez probablement pas utiliser une liste.