web-dev-qa-db-ja.com

キーを使用してLinkedHashMapでキー/値の位置を取得する方法

こんにちは、名前/年齢(文字列/整数)のペアを含むLinkedHashMap(情報と呼ばれる)があります。キーを入力した場合、どのようにしてキー/値の位置を取得できますかを知りたいです。たとえば、LinkedHashMapが{bob = 12、jeremy = 42、carly = 21}のように見え、jeremyを検索する場合、位置1として1を返す必要があります。info.getIndexのようなものを使用できると期待していました(「ジェレミー」)

32
Matt9Atkins

HashMapの実装は、一般的にIterationの順序付けられていません。

LinkedHashMap予測可能Iteration(挿入順序)の順序ですが、ListインターフェイスとLinkedList(キーセットの挿入順序を反映するもの)は、インデックスの位置自体も追跡しません。インデックスを見つけることも非常に非効率的です。 LinkedHashMapは、内部LinkedListへの参照も公開しません。

実際の "リンクリスト"の動作は実装固有です。実際にLinkedListのインスタンスを使用する人もいれば、直前と次のEntryを追跡するEntryを持つだけで、その実装として使用する人もいます。ソースを見ないで何も仮定しないでください。

キーを含むKeySetは、継承されたHashMapのバッキングデータ構造に配置するために使用されるハッシュアルゴリズムのため、順序も保証しません。だからそれは使えない。

独自の実装を作成せずにこれを行う唯一の方法は、ミラーリングIteratorを使用するLinkedListを歩いて、現在の場所でカウントを維持することです。データセット。

ソリューション

あなたが望むように聞こえるのは、元の挿入順序のインデックス位置KeySetのようなものでArrayListのキーをミラーリングする必要があり、同期を保つことです。 HashMapを更新して、位置を見つけるために使用します。 HashMapのサブクラスを作成し、たとえばIndexedHashMapを作成し、このArrayListを内部で追加し、内部ArrayListに委任する.getKeyIndex(<K> key)を追加します.indexOf()はおそらくこれを行うための最良の方法です。

これはLinkedHashMapが行うことですが、LinkedListの代わりにKeySetをミラーリングするArrayListを使用します。

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

LinkedHashMapには「予測可能な反復順序」があります( javadoc )。ただし、アイテムはその場所を知らないため、コレクションを取得して取得する必要があります。大きなマップを維持している場合は、ストレージに別の構造を使用することをお勧めします。

編集:明確化された反復

0
Mike D

Google Guavaライブラリの _com.google.common.collect.LinkedListMultimap_ を使用できます。このクラスのマルチマップの動作は必要ありません。keys()メソッドが挿入順序で返されることを保証し、リストの作成に使用できることです。indexOf()必要なインデックス位置を見つける

0
Paul Taylor

私はこの質問の重複の1つからの提案を見ました

キーではなくインデックスに基づいてLinkedHashMapから値を取得する方法

また、コメントで@schippiからの擬似コードとして説明されている提案が気に入りました。私はいくつかの作業Javaこのコードで他の人に役立つかもしれないコードだと思った

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