Je voulais obtenir un list
des éléments uniques d'un list
avec des éléments en double et l'ordre des éléments apparaissant dans la liste devrait être maintenue.
Pour ce faire, je aurais pu écrire un algorithme comme:
private ArrayList<T> getUnique(ArrayList<T> list)
{
// maintain a hashmap of numbers and a uniqueList to be returned(ArrayList<T>)
// Add element in result list and the hashmap if the element isn't already present in the hashmap, else just add in the hashmap
HashMap<T, Boolean> map = new HashMap<>();
ArrayList<T> uniqueList = new ArrayList<>();
for (T t: list)
{
if (map.get(t) == null)
{
// t wasn't present so, adding them in map as well as in the list
map.put(t, true);
uniqueList.add(t);
}
}
return uniqueList;
}
Cet algorithme prendra du O(n)
temps avec un O(n)
espace supplémentaire (pour HashMap).
Ou tout simplement, je aurais pu utiliser la syntaxe ci-dessous:
Set<T> set = new LinkedHashSet<>(list);
La syntaxe ci - dessus en Java est utilisé pour obtenir un set
des éléments uniques de list
l'ordre d'apparition des mêmes éléments que celui de list
. Ensuite convertir cet ensemble dans une liste. ( ArrayList<T> uniqueList = new ArrayList<>(set);
)
Je suppose la complexité de temps est également ici O(n)
. Je voulais savoir quel algorithme Java utilise pour cela.
Je vois la classe est nommé LinkedHashSet, donc je pensais qu'ils pourraient utiliser certains LinkedList
concepts pour y parvenir, je regardais dans le code source, et a trouvé ces trucs:
- Dans
LinkedHashSet.java
, le constructeur ressemble à :
143: public LinkedHashSet(Collection<? extends T> c) 144: { 145: super(c); 146: }
ici est la source.
- Alors, je regardais le constructeur de la classe parent -à- dire
HashSet
, j'ai trouvé:
public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
- Ensuite, je cherchais la
addAll
méthode, je l' ai trouvé dans laAbstractCollection
classe (qui est le grand - parent deHashSet
classe), la définition de la fonction est:
public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; }
C'est l' appel add
qui ressemble à :
public boolean add(E e) { throw new UnsupportedOperationException(); }
ici .
Je ne pouvais pas comprendre cela. Quel algorithme utilisent-ils pour cette tâche?
Pour quelqu'un qui cherche l'histoire
Base sur le code source de LinkedHashSet , HashSet , LinkedHashMap . Lors de la construction d' un LinkedHashSet
qui se prolonge HashSet
avec un autre collection (ligne LinkedHashSet.java 143),
public LinkedHashSet(Collection<? extends T> c)
{
super(c);
}
Qui appellera (ligne HashSet.java 136):
public HashSet(Collection<? extends T> c)
{
this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
addAll(c);
}
et ensuite appeler (ligne HashSet.java 122):
public HashSet(int initialCapacity, float loadFactor)
{
map = init(initialCapacity, loadFactor);
}
Étant donné que la init
méthode est en overridedLinkedHashSet
HashMap<T, String> init(int capacity, float load)
{
return new LinkedHashMap<T, String>(capacity, load);
}
Le support map
est un LinkedHashMap
.
Selon java doc de LinkedHashMap
Cette classe fournit toutes les opérations optionnelles Carte et permis null éléments. Comme HashMap, il fournit des performances en temps constant pour les opérations de base (addition, contient et supprimer), en supposant que les éléments fonction de hachage correctement se dispersent dans les seaux. La performance est susceptible d'être légèrement inférieur à celui de HashMap, en raison de la charge supplémentaire de maintenir la liste liée, à une exception près: itérer sur la collection-vues d'un LinkedHashMap nécessite un temps proportionnel à la taille de la carte, quelle que soit sa capacité . Itérer sur une table de hachage est susceptible d'être plus cher, ce qui nécessite un temps proportionnel à sa capacité.
Et la add
méthode HashSet
est -
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
D' où la complexité temporelle moyenne est O (n) pour la construction. Pour l'algorithme, je pense que vous pouvez lire le code de LinkedHashMap pour plus de détails. Pour en savoir plus Comment est la mise en œuvre interne de LinkedHashMap différent de la mise en œuvre HashMap? , HashSet vs LinkedHashSet