Salut, j'ai un LinkedHashMap (appelé info) qui contient des paires nom/âge (chaîne/int). Je veux savoir comment obtenir la position de la clé/valeur si j'entre la clé. Par exemple, si mon LinkedHashMap ressemblait à ceci {bob = 12, jeremy = 42, carly = 21} et que je devais rechercher jeremy, il devrait retourner 1 comme étant en position 1. J'espérais pouvoir utiliser quelque chose comme info.getIndex ("Jeremy")
HashMap
les implémentations en général ne sont pas ordonnées pour Iteration
.
LinkedHashMap
est prévisible ordonné pour Iteration
(ordre d'insertion) mais n'expose pas l'interface List
et un LinkedList
(qui est ce qui reflète l'ordre d'insertion du jeu de clés) ne suit pas non plus la position de l'index lui-même, il est également très inefficace de trouver l'index. Le LinkedHashMap
n'expose pas non plus la référence au LinkedList
interne.
Le comportement réel "Liste liée" est spécifique à l'implémentation. Certains peuvent en fait utiliser une instance de
LinkedList
certains ont justeEntry
suivre unEntry
précédent et suivant et l'utiliser comme implémentation. Ne présumez rien sans regarder la source.
Le KeySet
qui contient les clés ne garantit pas non plus l'ordre en raison des algorithmes de hachage utilisés pour le placement dans la structure de données de support du HashMap
hérité. Vous ne pouvez donc pas utiliser cela.
La seule façon de le faire, sans écrire votre propre implémentation, est de parcourir le Iterator
qui utilise le miroir LinkedList
et de garder un décompte où vous êtes, ce sera très inefficace avec de grandes ensembles de données.
Solution
Ce que cela ressemble à ce que vous voulez est positions d'index de l'ordre d'insertion d'origine, vous devez mettre en miroir les clés dans le KeySet
dans quelque chose comme un ArrayList
, le garder synchronisé avec des mises à jour du HashMap
et l'utiliser pour trouver la position. Création d'une sous-classe de HashMap
, disons IndexedHashMap
et ajout de ce ArrayList
en interne et ajout d'un .getKeyIndex(<K> key)
qui délègue au ArrayList
interne .indexOf()
est probablement la meilleure façon de procéder.
C'est ce que fait LinkedHashMap
mais avec un LinkedList
reflétant le KeySet
au lieu d'un ArrayList
.
int pos = new ArrayList<String>(info.keySet()).indexOf("jeremy")
LinkedHashMap a un "ordre d'itération prévisible" ( javadoc ). Cependant, les objets ne connaissent pas leur emplacement, vous devrez donc parcourir la collection pour l'obtenir. Si vous gérez une grande carte, vous souhaiterez peut-être utiliser une structure différente pour le stockage.
Modifier: itération clarifiée
Vous pouvez utiliser com.google.common.collect.LinkedListMultimap
dans la bibliothèque Google Guava . Vous n'avez pas besoin du comportement multimap de cette classe, ce que vous voulez, c'est que la méthode keys()
garantit qu'ils sont retournés dans l'ordre d'insertion et peuvent ensuite être utilisés pour construire une liste, vous pouvez utiliser la fonction indexOf()
pour trouver la position d'index requise
J'ai vu une suggestion de l'un des doublons de cette question à
Comment obtenir la valeur de LinkedHashMap en fonction de l'index et non de la clé?
et j'ai aimé la suggestion telle que décrite comme pseudo-code de @schippi dans les commentaires. Je pensais que certains codes Java Java pourraient être utiles à d'autres sur cette approche
import Java.util.ArrayList;
import Java.util.LinkedHashMap;
public class IndexedLinkedHashMap<K,V> extends LinkedHashMap<K,V> {
/**
*
*/
private static final long serialVersionUID = 1L;
ArrayList<K> al_Index = new ArrayList<K>();
@Override
public V put(K key,V val) {
if (!super.containsKey(key)) al_Index.add(key);
V returnValue = super.put(key,val);
return returnValue;
}
public V getValueAtIndex(int i){
return (V) super.get(al_Index.get(i));
}
public K getKeyAtIndex(int i) {
return (K) al_Index.get(i);
}
public int getIndexOf(K key) {
return al_Index.indexOf(key);
}
}