2017-02-11 7 views
1

私はHashMapとHastableをObjectのListとしてキーとして使用しようとしています。 下のコードは機能しません。 私はこのコードをデバッグするとき、私はHashMapのオブジェクトに新しいアイテムを入れるとどうなりますかTestMap4オブジェクトに3つの項目を持つだけで1Java - リスト<>をキーとしたHashMapの使用

List<String> lst = new ArrayList<>(); 
lst.add("Hello"); 
lst.add("World"); 

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>(); 
testMap4.put(lst, 1); 
testMap4.put(lst, 2); 
testMap4.put(lst, 5); 

がある期待それはなぜ機能しないのですか?

以下の新しい例でも同じ結果が得られます。私は2列の唯一の1文字を変更する場合

List<String> lst = new ArrayList<>(); 
lst.add("Hello"); 
lst.add("World"); 

List<String> lst2 = new ArrayList<>(); 
lst2.add("Hello"); 
lst2.add("World"); 

List<String> lst3 = new ArrayList<>(); 
lst3.add("Hello"); 
lst3.add("World"); 

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>(); 
testMap4.put(lst,1); 
testMap4.put(lst2,2); 
testMap4.put(lst3,5); 

(各リストは、同じ2文字列をcountains)、これはOKです

+0

マップのキー/値の部分を誤解しています(https://www.tutorialspoint.com/java/java_hashmap_class.htm)。マップは1つの値しか持てません。つまり、1つの固有キーに関連付けられています。同じキーで値を入力するので、既存の値を毎回変更します。 – JohnnyAW

+0

数字1、2、5のメーリングは何ですか?キー1,2,5に対してリスト(同じリスト)を入れようとしていますか?そうであれば、あなたのキーと値が間違った方法で返されます –

+0

各項目のリストのハッシュコードを変更する方法はありますか?一意であると特定するには? – ManWithNoName

答えて

4

あなたはHashMapという概念を理解していません。

問題はあなたは毎回同じ鍵を使用しています。 Hashmap

testMap4.put(lst, 1);  <----same key, different value 
testMap4.put(lst, 2);  <----same key, different value 
testMap4.put(lst, 5);  <----same key, different value 

Hashmapに格納されたすべての値は、そこにその特定の値で保存されkeyだとHashMapについてHashmap

の重要事項に格納された各値についてユニークです。

1-ハッシュマップには、キーに基づく値が含まれています。

2 - これには固有の要素のみが含まれています。

3 1つのヌルキーと複数のヌル値を持つことがあります。

4-順序を保持しません。

HashMap<Integer,String> hm=new HashMap<Integer,String>(); 

第二に、彼らがマップに挿入された後、リストのいずれかが変更された場合、未定義の動作に重要な結果として変更可能なオブジェクト(List<>)を使用。ハッシュコードは、List(Javadocを参照)のコントラクトに従って計算されます。これは、エントリが最初にマップに挿入されたときだけです。リストの内容を変更すると、ハッシュコードが変更され、そのエントリを見つけることができなくなります。 HashMap<>でキーとしてList<>(または任意の変更可能なオブジェクト)を使用して

は™本当に悪い考えです。

0

あなたが別の値を格納するために同じキー毎回使用しているので、それが動作しませんすべての値が同じキーにマッピングされているため、この値は前の値を上書きするため、hashmapは最後の値のみを格納しています。

0

HashMapは、HashMapに入れたキーオブジェクトに対してhashCode()メソッドを呼び出します。

使用しているキークラス(あなたの場合はList<>)に対してはオーバーライドしていないので、一意のオブジェクトIDを返すjava.lang.ObjecthashCode()メソッドを呼び出します。

同じオブジェクトをマップに3回配置すると、3回連続で同じキーを配置することになります。

List<String> lst1 = new ArrayList<>(); 
lst.add("Hello"); 
lst.add("World"); 
List<String> lst2 = new ArrayList<>(); 
List<String> lst3 = new ArrayList<>(); 

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>(); 
testMap4.put(lst1, 1); 
testMap4.put(lst2, 2); 
testMap4.put(lst3, 5); 

あなたのマップには3つのエントリがあります。

あなたはHashMapのキーとして使用するために、リストの内容以上のハッシュコードが必要な場合は、見ています。あなた常に両方のメソッドをオーバーライドする必要があること

static int java.util.Objects.hash(Object... values) 
static boolean java.util.Arrays.equals(Object[] a, Object[] a2) 

を忘れてはいけませんhashCode()およびequals()。そのうちの1つを上書きすれば即座に死んでしまうでしょう! ;)

+0

ArrayList <>クラスを拡張し、次のようにhashCode()メソッドをオーバーライドしました: '@Override public int hashCode(){ return UUID.randomUUID()。hashCode(); } '私の場合はうまくいくようです。 – ManWithNoName

+0

これは間違いが間違っています! あなたが乱数を返すと、 'put(o、x)'のhashCodeは 'get(o)'のhashCodeと違うでしょう。つまり、HashMapから値を取り出すことはできません再び! マップに1つのStringをキーとして2回入れると、2番目のputも最初のput!をオーバーライドします。これがマップの仕組みです。 –

+0

私は、AbstractListのequalsとcompareを調べました。それらは既に実装されており、Listの_contents_に基づいてhashCodeとequalsを与えています。だから、あなたがマップに入れたリストを変更しても、同じ値を取得しない限り、何かをオーバーライドする必要はありません。この場合、私はhashCodeとCompareをオーバーライドして 'Object's equalsを呼び出して比較します。 –

関連する問題