web-dev-qa-db-fra.com

Comment obtenir la position de la clé / valeur dans LinkedHashMap en utilisant sa clé

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")

32
Matt9Atkins

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 juste Entry suivre un Entry 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.

27
user177800
int pos = new ArrayList<String>(info.keySet()).indexOf("jeremy")
14
marioosh

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

0
Mike D

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

0
Paul Taylor

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);
    }

}
0
Rocksalt