2012-04-02 6 views
12

HashMapのキーにArrayListを追加することは可能でしょうか。私はバイグラムの頻度を維持したいと思います。バイグラムがキーであり、値はその頻度です。ハッシュマップのキーとしてArrayList

「he is」のような各バイグラムについては、ArrayListを作成してHashMapに挿入します。しかし、私は正しい出力を得ていません。

class Bigram{ 
    private String firstItem; 
    private String secondItem; 

    <getters/setters> 

    @Override 
    public int hashCode(){ 
     ... 
    } 

    @Override 
    public boolean equals(){ 
     ... 
    } 
} 

の代わりに、項目(2)の限られた数の動的なコレクションを使用して:あなたはこのようなものを使用することはできませんなぜ

public HashMap<ArrayList<String>, Integer> getBigramMap (String word1,String word2){ 
    HashMap<ArrayList<String>, Integer> hm = new HashMap<ArrayList<String>, Integer>(); 
    ArrayList<String> arrList1 = new ArrayList<String>(); 
    arrList1 = getBigram(word1, word2);  
    if(hm.get(arrList1) !=null){ 
     hm.put(arrList1, hm.get(arrList1)+1); 
    } 
     else { 

      hm.put(arrList1, 1); 
     } 
    System.out.println(hm.get(arrList1)); 
    return hm; 
} 


public ArrayList<String> getBigram(String word1, String word2){ 
    ArrayList<String> arrList2 = new ArrayList<String>(); 
    arrList2.add(word1); 
    arrList2.add(word2); 
    return arrList2; 
} 

答えて

2

+1

私はセッターを除外して不変にします。おそらく建設後にそのクラスのオブジェクトを変更する理由はありません。 –

+0

+1 - 実際には、これはおそらく**スペースを節約します。なぜなら、Bigramクラスは32ビットの 'length'フィールドのオーバーヘッドを持たないからです。 –

-3

ArrayList.equals()java.lang.Objectから継承されます。したがって、ArrayListのequals()はリストの内容とは関係ありません。

あなたがマップキーとしてのArrayListを使用する場合は、同じ順序で同じ内容を持つ2つの配列リストがequals()への呼び出しにtrueを返すと、同じハッシュコードを返すようにするためにequals()hashcode()をオーバーライドする必要がありますhashcode()への電話で

には、単純なStringをキーとしてArrayListを使用するのには、があります。

編集:私を無視する、ヨアヒム・サウアーが指摘したように、私は間違っているので面白くない。

+5

実際には、 'ArrayList'は' AbstractList.equals() 'を使用しています。実際、すべての正しい 'List'実装では、' equals() 'と' hashCode() 'の実装に準拠する必要があります。 –

+1

ああ、訂正してくれてありがとう。私はちょうどArrayListのソースを素早くスキャンし、さらに上に行く気にしなかった - 私の部分の壮大な失敗。 – mcfinnigan

+0

ヒント:Eclipseでアウトラインダイアログを開くにはCtrl-Oを押し、 'equals'と入力し、定義がない場合はCtrl + Oをもう一度押して継承されたメンバーも見て、実際に継承されたメンバーが4つあることを確認します(' Object'、 Collection'、 'List'、' AbstractList')を指定します。他のIDEにも同様のショートカットがあると確信しています。 –

18

はい、あなたは、ハッシュマップのキーとしてArrayList Sを持つことができますが、彼らは可変あるので、それは、非常に悪い考えです。

ArrayListを何らかの方法で変更した場合、キーは挿入されたときと同じであるため、マッピングは基本的に失われます。

経験則は、不変のデータ型のみをハッシュマップのキーとして使用することです。

final class Bigram { 

    private final String word1, word2; 

    public Bigram(String word1, String word2) { 
     this.word1 = word1; 
     this.word2 = word2; 
    } 

    public String getWord1() { 
     return word1; 
    } 

    public String getWord2() { 
     return word2; 
    } 

    @Override 
    public int hashCode() { 
     return word1.hashCode()^word2.hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     return (obj instanceof Bigram) && ((Bigram) obj).word1.equals(word1) 
             && ((Bigram) obj).word2.equals(word2); 
    } 
} 
+0

それは可変であることを除けば、彼が実際に働いているのであれば、 'Bigram'クラスを導入するのは良い考えです。 –

1

が、これは動作しますが、これを試してみてください:アレックスStybaevによって示唆されるように、あなたはおそらく、このようなBigramクラスを作成します。

public Map<List, Integer> getBigramMap (String word1,String word2){ 
    Map<List,Integer> hm = new HashMap<List, Integer>(); 
    List<String> arrList1 = new ArrayList<String>(); 
    arrList1 = getBigram(word1, word2);  
    if(hm.get(arrList1) !=null){ 
     hm.put(arrList1, hm.get(arrList1)+1); 
    } 
    else { 
     hm.put(arrList1, 1); 
    } 

    System.out.println(hm.get(arrList1)); 
    return hm; 
} 
+0

この問題は、** List **をパラメタライズすることができません。あなたも私にそれについて考えてもらえますか?または私はそれのための別のスレッドを開始する必要があります。 – thetna

+0

これを使用すると、任意のタイプのリストをマップに渡すことができます。リストには、文字列、整数、またはユーザー定義のオブジェクトを指定できます。 – vikiiii

2

the documentationから:

注:可変オブジェクトをマップ キーとして使用されている場合には細心の注意を払わなければなりません。 オブジェクトがマップ内のキーである間に、 がequalsの比較に影響するように変更された場合、マップの動作は指定されません。この禁止事項の特別な場合は、マップがキーとして自分自身を含むことが許容されていないことです( )。地図が値として含まれることが許容されるのは ですが、 が推奨されています。equalshashCodeの方法は、もはや ではありません。

はあなたがhashCodeequalsのためのキーとして可変オブジェクトを使用している際に世話をする必要があります。

結論は、不変のオブジェクトをキーとして使用する方が良いということです。

0

確かに可能です。あなたのputに問題があると思われます。このバイグラムでエントリを削除し、更新された値を挿入してください。

-1

キーがArrayListであり、入力がJVMによって行われるかどうかを確認するには、以下のコードを確認してください。 ここに書きますTesthashCodeEqualsクラスのhashCodeとequalsメソッド

package com.msq; 

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

class TesthashCodeEquals { 
    private int a; 
    private int b; 

    public TesthashCodeEquals() { 
     // TODO Auto-generated constructor stub 
    } 



    public TesthashCodeEquals(int a, int b) { 
     super(); 
     this.a = a; 
     this.b = b; 
    } 



    public int getA() { 
     return a; 
    } 

    public void setA(int a) { 
     this.a = a; 
    } 

    public int getB() { 
     return b; 
    } 

    public void setB(int b) { 
     this.b = b; 
    } 

    public int hashCode() { 

     return this.a + this.b; 
    } 

    public boolean equals(Object o) { 

     if (o instanceof TesthashCodeEquals && o != null) { 

      TesthashCodeEquals c = (TesthashCodeEquals) o; 

      return ((this.a == c.a) && (this.b == c.b)); 

     } else 
      return false; 
    } 
} 

public class HasCodeEquals { 
    public static void main(String[] args) { 

     Map<List<TesthashCodeEquals>, String> m = new HashMap<>(); 

     List<TesthashCodeEquals> list1=new ArrayList<>(); 
     list1.add(new TesthashCodeEquals(1, 2)); 
     list1.add(new TesthashCodeEquals(3, 4)); 

     List<TesthashCodeEquals> list2=new ArrayList<>(); 
     list2.add(new TesthashCodeEquals(10, 20)); 
     list2.add(new TesthashCodeEquals(30, 40)); 


     List<TesthashCodeEquals> list3=new ArrayList<>(); 
     list3.add(new TesthashCodeEquals(1, 2)); 
     list3.add(new TesthashCodeEquals(3, 4)); 



     m.put(list1, "List1"); 
     m.put(list2, "List2"); 
     m.put(list3, "List3"); 

     for(Map.Entry<List<TesthashCodeEquals>,String> entry:m.entrySet()){ 
      for(TesthashCodeEquals t:entry.getKey()){ 
       System.out.print("value of a: "+t.getA()+", value of b: "+t.getB()+", map value is:"+entry.getValue()); 
       System.out.println(); 
      } 
      System.out.println("######################"); 
     } 

    } 
} 

output: 

value of a: 10, value of b: 20, map value is:List2 
value of a: 30, value of b: 40, map value is:List2 
###################### 
value of a: 1, value of b: 2, map value is:List3 
value of a: 3, value of b: 4, map value is:List3 
###################### 

これにより、List内のオブジェクトの数とobject内のvalriabeの値がチェックされます。オブジェクトの数が同じで、インスタンス変数の値も同じ場合は、重複キーとみなしてキーをオーバーライドします。

今はLIST3

list3.add(新しいTesthashCodeEquals(2、2))上のオブジェクトの値のみを変更した場合。

それが印刷されます:

output 
    value of a: 2, value of b: 2, map value is:List3 
    value of a: 3, value of b: 4, map value is:List3 
    ###################### 
    value of a: 10, value of b: 20, map value is:List2 
    value of a: 30, value of b: 40, map value is:List2 
    ###################### 
    value of a: 1, value of b: 2, map value is:List1 
    value of a: 3, value of b: 4, map value is:List1 
###################### 

それは常にリスト内のオブジェクトの数と、オブジェクトのインスタンス変数の値をチェックするように。私はこのソリューションを作ってみた

おかげ

1

。たとえば、入力リストが変更された場合、キーは意図したとおりにそのまま残りますが、Listの項目が変更可能な場合はクローンされますリストにはそのアイテムと同じ参照があり、その結果、キー自体が変更されます)。

import java.util.ArrayList; 

public class ListKey<T> { 
    private ArrayList<T> list; 

    public ListKey(ArrayList<T> list) { 
     this.list = (ArrayList<T>) list.clone(); 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 

     for (int i = 0; i < this.list.size(); i++) { 
      T item = this.list.get(i); 
      result = prime * result + ((item == null) ? 0 : item.hashCode()); 
     } 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     return this.list.equals(obj); 
    } 
} 

--------- 
    public static void main(String[] args) { 

     ArrayList<Float> createFloatList = createFloatList(); 
     ArrayList<Float> createFloatList2 = createFloatList(); 

     Hashtable<ListKey<Float>, String> table = new Hashtable<>(); 
     table.put(new ListKey(createFloatList2), "IT WORKS!"); 
     System.out.println(table.get(createFloatList2)); 
     createFloatList2.add(1f); 
     System.out.println(table.get(createFloatList2)); 
     createFloatList2.remove(3); 
     System.out.println(table.get(createFloatList2)); 
    } 

    public static ArrayList<Float> createFloatList() { 
     ArrayList<Float> floatee = new ArrayList<>(); 
     floatee.add(34.234f); 
     floatee.add(new Float(33)); 
     floatee.add(null); 

     return floatee; 
    } 

Output: 
IT WORKS! 
null 
IT WORKS! 
+0

私はそれをテストしましたが、何らかの理由で解決策が信頼できないことがわかりました。それは有効ですか? – Javo

関連する問題