Lors du traitement de grandes quantités de données, je suis souvent amené à:
HashSet<String> set = new HashSet<String> ();
//Adding elements to the set
ArrayList<String> list = new ArrayList<String> (set);
Quelque chose comme "dumping" le contenu de l'ensemble dans la liste. Je fais généralement cela car les éléments que je rajoute contiennent souvent des doublons que je veux supprimer, ce qui semble être un moyen facile de les supprimer.
Avec seulement cet objectif en tête (éviter les doublons), je pourrais aussi écrire:
ArrayList<String> list = new ArrayList<String> ();
// Processing here
if (! list.contains(element)) list.add(element);
//More processing here
Et donc pas besoin de "dumping" l'ensemble dans la liste. Cependant, je ferais une petite vérification avant d’insérer chaque élément (ce que je suppose aussi que HashSet fait aussi)
L'une des deux possibilités est-elle clairement plus efficace?
L'ensemble donnera de bien meilleures performances (O(n)
vs O(n^2)
pour la liste), ce qui est normal car l'appartenance à un ensemble (l'opération contains
) est l'objectif very d'un ensemble.
Contient pour une HashSet
est O(1)
par rapport à O(n)
pour une liste. Par conséquent, vous ne devez jamais utiliser une liste si vous devez souvent exécuter contains
.
ArrayList
utilise un tableau pour stocker les données. Le ArrayList.contains
sera de O(n) complexité. Donc, essentiellement, rechercher dans le tableau encore et encore aura la complexité O(n^2)
.
Alors que HashSet
utilise un mécanisme de hachage pour stocker les éléments dans leurs compartiments respectifs. L'opération de HashSet
sera plus rapide pour une longue liste de valeurs. Il atteindra l'élément dans O(1)
.
J'ai fait un test alors vérifiez le résultat:
Pour les éléments SAME STRING dans un HashSet, TreeSet, ArrayList et LinkedList, voici les résultats de
Basé sur les résultats ci-dessus, il n'y a PAS une grosse différence entre l'utilisation de la liste de tableaux et celle d'un ensemble. Vous pouvez peut-être essayer de modifier ce code et remplacer le String par votre Object et voir les différences ensuite ...
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
Set<String> treeSet = new TreeSet<>();
List<String> arrayList = new ArrayList<>();
List<String> linkedList = new LinkedList<>();
List<String> base = new ArrayList<>();
for(int i = 0; i<5000000; i++){
if(i%100000==0) System.out.print(".");
base.add(UUID.randomUUID().toString());
}
System.out.println("\nBase size : " + base.size());
String item = base.get(25000);
System.out.println("SEARCHED ITEM : " + item);
hashSet.addAll(base);
treeSet.addAll(base);
arrayList.addAll(base);
linkedList.addAll(base);
long ms = System.currentTimeMillis();
System.out.println("hashSet.contains(item) ? " + (hashSet.contains(item)? "TRUE " : "FALSE") + (System.currentTimeMillis()-ms) + " ms");
System.out.println("treeSet.contains(item) ? " + (treeSet.contains(item)? "TRUE " : "FALSE") + (System.currentTimeMillis()-ms) + " ms");
System.out.println("arrayList.contains(item) ? " + (arrayList.contains(item)? "TRUE " : "FALSE") + (System.currentTimeMillis()-ms) + " ms");
System.out.println("linkedList.contains(item) ? " + (linkedList.contains(item)? "TRUE " : "FALSE") + (System.currentTimeMillis()-ms) + " ms");
}
Si vous n'avez pas besoin d'une liste, j'utiliserais simplement un ensemble. Il s'agit de la collection naturelle à utiliser si l'ordre n'a pas d'importance et que vous souhaitez ignorer les doublons.
Vous pouvez faire les deux si vous avez besoin d’une liste sans doublons.
private Set<String> set = new HashSet<>();
private List<String> list = new ArrayList<>();
public void add(String str) {
if (set.add(str))
list.add(str);
}
De cette façon, la liste ne contiendra que des valeurs uniques, l'ordre d'insertion d'origine sera conservé et l'opération sera O (1).
Vous pouvez ajouter des éléments à la liste elle-même ..__ Ensuite, pour déduire -
HashSet<String> hs = new HashSet<>(); // new hashset
hs.addAll(list); // add all list elements to hashset (this is the dedup, since addAll works as a union, thus removing all duplicates)
list.clear(); // clear the list
list.addAll(hs); // add all hashset elements to the list
Si vous avez juste besoin d'un ensemble avec déduction, vous pouvez également utiliser addAll () sur un autre ensemble, de sorte qu'il ne possède que des valeurs uniques.