web-dev-qa-db-ja.com

Javaの多値ハッシュテーブル

ハッシュテーブルの同じキーに複数の値を含めることはできますか?そうでない場合、使用できるそのようなクラスまたはインターフェースを提案できますか?

25
raji

いいえ。それはハッシュテーブルのようなものです。

ただし、Map<YourKeyObject, List<YourValueObject>>およびリストが存在しない場合にリストを作成するためのいくつかのユーティリティメソッド、または Multimap from Google Collections のようなものを使用します。

例:

String key = "hello";
Multimap<String, Integer> myMap = HashMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // prints either "[1, 5000]" or "[5000, 1]"
myMap = ArrayListMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // always prints "[1, 5000]"

Multimapは、自家製のソリューションのexact等価ではないことに注意してください。 Hashtable はすべてのメソッドを同期しますが、Multimapはそのような保証をしません。つまり、Multimapを使用すると、複数のスレッドで使用している場合に問題が発生する可能性があります。マップが1つのスレッドでのみ使用されている場合、違いはありません(とにかくHashMapの代わりに Hashtable を使用しているはずです)。

21
Michael Myers

ハッシュテーブルの値はObjectなので、リストを保存できます

11
Eric

ハッシュテーブルでは、キーと値のペアを使用して情報を格納します。

Javaでは、 Hashtable クラスは単一のキーに対して単一の値を受け入れます。以下は、複数の値を単一のキーに関連付ける試みの例です。

Hashtable<String, String> ht = new Hashtable<String, String>();

ht.put("Answer", "42");
ht.put("Hello", "World");    // First value association for "Hello" key.
ht.put("Hello", "Mom");      // Second value association for "Hello" key.

for (Map.Entry<String, String> e : ht.entrySet()) {
  System.out.println(e);
}

単一のキー("World")に複数の値("Mom""Hello")を含めようとすると、Hashtableのエントリを出力するために次の結果になります。

Answer=42
Hello=Mom

"Hello""World"のキーと値のペアがHashtableにありません。2番目の"Hello"と "Mom"エントリだけがHashtableにあります。これは、Hashtableの単一のキーに複数の値を関連付けることはできないことを示しています。


ここで本当に必要なのは multimap で、これにより複数の値を単一のキーに関連付けることができます。

マルチマップの1つの実装は Multimap from Google Collections です。

Multimap<String, String> mm = HashMultimap.create();

mm.put("Answer", "42");
mm.put("Hello", "World");
mm.put("Hello", "Mom");

for (Map.Entry<String, String> e : mm.entries()) {
  System.out.println(e);
}

これは、Hashtableを使用した上記の例と似ていますが、動作がまったく異なります。Multimapを使用すると、単一のキーに複数の値を関連付けることができます。上記のコードを実行した結果は次のとおりです。

Answer=42
Hello=Mom
Hello=World

ご覧のように、"Hello"キーの場合、それに関連付けられている"Mom"および"World"の値。 Hashtableとは異なり、値の1つを破棄して別の値で置き換えることはありません。 Multimapは、各キーの複数の値を保持できます。

8
coobird

さらに別のマルチマップの答えを出すのではなく、なぜこれを実行するのかを尋ねます。

複数の値は関連していますか?はいの場合は、それらを保持するデータ構造を作成することをお勧めします。いいえの場合、おそらく別のマップを使用する方が適切です。

キーに基づいて反復できるように、それらをまとめていますか? SkipListのような別の索引付けデータ構造を探したい場合があります。

7
kdgregory

他の人が指摘したように、いいえ。代わりに、同じキーに多くの値をマップできるMultimapの使用を検討してください。

の GoogleコレクションupdateGuava )ライブラリには1つの実装が含まれており、おそらくあなたの最善の策です。

Edit:もちろん Ericの提案 のようにして、コレクションを値としてHashtable(またはMap、より一般的には)、しかしそれは不必要な定型コードを自分で書くことを意味します。 Googleコレクションのようなライブラリを使用すると、低レベルの「配管」が自動的に行われます。バニラの代わりにマルチマップを使用してコードを簡略化する方法の 良い例 を確認してくださいJavaコレクションクラス。

5
Jonik

最初に何をするかを示す答えはありませんでした。

OOの能力で私がこれまでに行った最大のジャンプは、少しでも役立つかもしれないと思われるときに常に別のクラスを作成することにしたときでした-これは私が今までに経験したことの1つですそのパターンに従うことから学んだ。

ほぼ常に、ハッシュテーブルに配置しようとしているオブジェクト間に関係があることがわかりました。たいていの場合、1つまたは2つのメソッドであっても、クラスの余地があります。

実際、HashMap型の構造も必要ないことがよくあります。単純なHashSetで十分です。

主キーとして保存しているアイテムは、新しいオブジェクトのIDになる可能性があります。そのため、その1つのオブジェクトのみを参照する等価メソッドとハッシュメソッドを作成できます(Eclipseでは、等価メソッドとハッシュメソッドを簡単に作成できます)。これにより、新しいオブジェクトは元のオブジェクトとまったく同じように保存、並べ替え、および取得され、プロパティを使用して残りのアイテムを格納します。

私がそれをするとき、ほとんどの場合、そこにも行くいくつかのメソッドがあり、それを知る前に、ずっとそこにあるはずであるが認識されていない本格的なオブジェクトと、大量のゴミがある私のコードからの要因。

それをより「ベイビーステップ」にするために、私はしばしば元のクラスに含まれる新しいクラスを作成します-そのようにスコープすることが理にかなっている場合は、メソッド内にクラスを含めることさえあります-そして私はそれを移動しますそれがファーストクラスのクラスであることがより明確になるにつれて、.

4
Bill K

自分で作る:

Map<Object, List<Object>> multiMap = new HashMap<Object, List<Object>>();

たす:

  public void add(String key, Object o) {
    List<Object> list;
    if (multiMap.containsKey(key)) {
      list = multiMap.get(key);
      list.add(o);
    } else {
      list = new ArrayList<Object>();
      list.add(o);
      multiMap.put(key, list);
    }
  }
4
Cambium

マルチマップおよび類似のそのようなコレクションについては、 Googleコレクションライブラリ を参照してください。組み込みのコレクションは、これを直接サポートしていません。

2
Carl Manaster

あなたが探しているのは Multimap です。 google collections api は、これの素晴らしい実装と、使用することを学ぶ価値のある他の多くを提供します。強くお勧めします!

2
bendin

MultiMap と呼ばれるものを使用する必要があります。これは厳密にはマップではありませんが、別のAPIです。 Map <K、List <V >>とほぼ同じですが、entrySet()やvalues()などのメソッドはありません。

1
Mark Renouf

シンプル。の代わりに Hashtable<Key, Value>、 使用する Hashtable<Key, Vector<Value>>

1
luiscubal

GoogleのGuavaライブラリなしのコードを以下に示します。これは、キーとしてダブル値に使用され、ソートされた順序です

Map<Double,List<Object>> multiMap = new TreeMap<Double,List<Object>>();

for( int i= 0;i<15;i++)
{
    List<Object> myClassList = multiMap.get((double)i);
    if(myClassList == null)
    {
        myClassList = new ArrayList<Object>();
        multiMap.put((double) i,myClassList);
    }
    myClassList.add("Value "+ i);
}

List<Object> myClassList = multiMap.get((double)0);
if(myClassList == null)
{
    myClassList = new ArrayList<Object>();
    multiMap.put( (double) 0,myClassList);
}
myClassList.add("Value Duplicate");
for (Map.Entry entry : multiMap.entrySet()) 
{
  System.out.println("Key = " + entry.getKey() + ", Value = " +entry.getValue());
}
0
Somnath Kadam

Googleコレクションとは別に、MultiMap用の Apache Commons Collection オブジェクトがあります。

0
sheki