Si quelqu'un connaît Objective-C, il existe une collection appelée NSOrderedSet
qui agit comme Set et ses éléments sont accessibles en tant que ceux de Array.
Y at-il quelque chose comme ça en Java?
J'ai entendu dire qu'il existe une collection appelée LinkedHashMap
, mais je n'ai rien trouvé de tel pour un ensemble.
Jetez un oeil à LinkedHashSet class
Chaque ensemble a un itérateur (). L'itérateur d'un HashSet normal est assez aléatoire, un TreeSet le fait par ordre de tri, un LinkedHashSet iterator itère par ordre d'insertion.
Cependant, vous ne pouvez pas remplacer un élément dans un LinkedHashSet. Vous pouvez en supprimer un et en ajouter un autre, mais le nouvel élément ne sera pas à la place de l'original. Dans un LinkedHashMap, vous pouvez remplacer une valeur pour une clé existante, puis les valeurs seront toujours dans l'ordre d'origine.
En outre, vous ne pouvez pas insérer à une certaine position.
Vous feriez peut-être mieux d'utiliser un ArrayList avec une vérification explicite pour éviter d'insérer des doublons.
Jetez un coup d’œil au doc API standard Java . Juste à côté de LinkedHashMap
, il y a un LinkedHashSet
. Mais notez que l'ordre dans ceux-ci est l'ordre d'insertion, pas l'ordre naturel des éléments. Et vous ne pouvez qu'itérer dans cet ordre, pas d'accès aléatoire (sauf en comptant les étapes d'itération).
Il existe également une interface SortedSet
implémentée par TreeSet
et ConcurrentSkipListSet
. Les deux autorisent l’itération dans l’ordre naturel de leurs éléments ou a Comparator
, mais pas dans un accès aléatoire ni dans un ordre d’insertion.
Pour une structure de données ayant à la fois un accès efficace par index et pouvant implémenter efficacement le critère défini, vous aurez besoin d'une liste de sauts , mais cette fonctionnalité n'est pas implémentée dans l'API standard Java facile à trouver sur internet.
TreeSet
est commandé.
http://docs.Oracle.com/javase/6/docs/api/Java/util/TreeSet.html
Essayez d’utiliser Java.util.TreeSet
qui implémente SortedSet
.
Pour citer le doc:
"Les éléments sont classés en utilisant leur ordre naturel, ou par un comparateur fourni au moment de la création du jeu, en fonction du constructeur utilisé"
Notez que ajouter, supprimer et contient un journal de coût en temps (n).
Si vous souhaitez accéder au contenu de l'ensemble sous forme de tableau, vous pouvez le convertir en procédant comme suit:
YourType[] array = someSet.toArray(new YourType[yourSet.size()]);
Ce tableau sera trié avec les mêmes critères que TreeSet (naturel ou par un comparateur), ce qui aura souvent un avantage au lieu de faire un Arrays.sort ()
treeset est un ensemble ordonné, mais vous ne pouvez pas y accéder via un index d'éléments, il vous suffit de parcourir ou d'aller au début/à la fin.
Vous pouvez également obtenir un utilitaire dans une carte bidirectionnelle telle que le BiMap
from Google Guava
Avec un BiMap
, vous pouvez très efficacement mapper un Integer (pour un accès aléatoire à un index) à tout autre type d'objet. BiMap
s sont un-à-un, donc tout entier donné a au plus un élément qui lui est associé et tout élément a un entier associé. Il repose intelligemment sur deux instances HashTable
. Il utilise donc presque le double de mémoire, mais il est beaucoup plus efficace qu'une List
personnalisée dans la mesure où il est traité car contains()
(qui est appelé lorsqu'un élément est ajouté existe) est une opération à temps constant et conviviale en parallèle comme celle de HashSet
, alors que la mise en oeuvre de List
est BEAUCOUP plus lente.
Si nous parlons d'une mise en oeuvre peu coûteuse de la liste de sauts, je me demande en termes de gros O, quel est le coût de cette opération
YourType [] array = someSet.toArray (new YourType [yourSet.size ()]);
Je veux dire qu'il est toujours bloqué dans la création d'un tableau entier, c'est donc O (n):
Java.util.Arrays#copyOf
IndexedTreeSet à partir du indexed-tree-map project fournit cette fonctionnalité (ensemble trié/trié avec accès par index semblable à une liste).
J'avais un problème similaire. Je n'avais pas vraiment besoin d'un ensemble ordonné mais plutôt d'une liste avec une variable indexOf
/contains
rapide. Comme je n'ai rien trouvé là-bas, j'en ai mis en place un moi-même. Voici le code, il implémente Set
et List
, bien que toutes les opérations de liste en bloc ne soient pas aussi rapides que les versions ArrayList
.
disclaimer: non testé
import Java.util.ArrayList;
import Java.util.HashMap;
import Java.util.Set;
import Java.util.Collection;
import Java.util.Comparator;
import Java.util.function.Predicate;
import Java.util.function.UnaryOperator;
import static Java.util.Objects.requireNonNull;
/**
* An ArrayList that keeps an index of its content so that contains()/indexOf() are fast. Duplicate entries are
* ignored as most other Java Set's do.
*/
public class IndexedArraySet<E> extends ArrayList<E> implements Set<E> {
public IndexedArraySet() { super(); }
public IndexedArraySet(Iterable<E> c) {
super();
addAll(c);
}
private HashMap<E, Integer> indexMap = new HashMap<>();
private void reindex() {
indexMap.clear();
int idx = 0;
for (E item: this) {
addToIndex(item, idx++);
}
}
private E addToIndex(E e, int idx) {
indexMap.putIfAbsent(requireNonNull(e), idx);
return e;
}
@Override
public boolean add(E e) {
if(indexMap.putIfAbsent(requireNonNull(e), size()) != null) return false;
super.add(e);
return true;
}
@Override
public boolean addAll(Collection<? extends E> c) {
return addAll((Iterable<? extends E>) c);
}
public boolean addAll(Iterable<? extends E> c) {
boolean rv = false;
for (E item: c) {
rv |= add(item);
}
return rv;
}
@Override
public boolean contains(Object e) {
return indexMap.containsKey(e);
}
@Override
public int indexOf(Object e) {
if (e == null) return -1;
Integer i = indexMap.get(e);
return (i == null) ? -1 : i;
}
@Override
public int lastIndexOf(Object e) {
return indexOf(e);
}
@Override @SuppressWarnings("unchecked")
public Object clone() {
IndexedArraySet clone = (IndexedArraySet) super.clone();
clone.indexMap = (HashMap) indexMap.clone();
return clone;
}
@Override
public void add(int idx, E e) {
if(indexMap.putIfAbsent(requireNonNull(e), -1) != null) return;
super.add(idx, e);
reindex();
}
@Override
public boolean remove(Object e) {
boolean rv;
try { rv = super.remove(e); }
finally { reindex(); }
return rv;
}
@Override
public void clear() {
super.clear();
indexMap.clear();
}
@Override
public boolean addAll(int idx, Collection<? extends E> c) {
boolean rv;
try {
for(E item : c) {
// check uniqueness
addToIndex(item, -1);
}
rv = super.addAll(idx, c);
} finally {
reindex();
}
return rv;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean rv;
try { rv = super.removeAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean rv;
try { rv = super.retainAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
boolean rv;
try { rv = super.removeIf(filter); }
finally { reindex(); }
return rv;
}
@Override
public void replaceAll(final UnaryOperator<E> operator) {
indexMap.clear();
try {
int duplicates = 0;
for (int i = 0; i < size(); i++) {
E newval = requireNonNull(operator.apply(this.get(i)));
if(indexMap.putIfAbsent(newval, i-duplicates) == null) {
super.set(i-duplicates, newval);
} else {
duplicates++;
}
}
removeRange(size()-duplicates, size());
} catch (Exception ex) {
// If there's an exception the indexMap will be inconsistent
reindex();
throw ex;
}
}
@Override
public void sort(Comparator<? super E> c) {
try { super.sort(c); }
finally { reindex(); }
}
}