2

したがって、文字列のリストから文字列へのマップを作成したいのですが、正しく機能させることができません:

これが私が行ったすべてのコードであり、その理由がわかるまで先に進むことはできません:

Map<List<String>, String> test = new HashMap<List<String>, String>();
test.put( new ArrayList<String>(), "s1");
test.put( new ArrayList<String>(), "s2");
test.put( new ArrayList<String>(), "s3");

System.out.println(test.size());

私は1を取得します、それは3であるべきです!! 3 つの個別のオブジェクトに対して 3 つの呼び出しを行ったときに、オブジェクトが 1 つしか追加されないのはなぜですか? 誤って同じオブジェクトをコレクションに追加する危険性は承知していますが、特に配置ごとに新しい ArrayList を作成したため、まったく新しいオブジェクトが作成されました。

それでは、なぜ Map にはオブジェクトが 1 つしかないのでしょうか? ありがとう!

4

5 に答える 5

3

ArrayList#hashCode() は、それらすべてに対して同じものを返しています。そのソースを見ると: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractList.java#AbstractList.hashCode%28 %29

要素がない場合、またはすべて同じ要素がある場合、hashCode が同じであることがわかります。

それを修正すると、正常に動作するはずです。Map を使用するか、hashCode を何らかの方法で変更します。

于 2013-02-12T05:24:00.480 に答える
3

これを試して:

Map<String,List<String>> test = new HashMap<String,List<String>>();
test.put("s1", new ArrayList<String>());
test.put("s2", new ArrayList<String>());
test.put("s3", new ArrayList<String>());

System.out.println(test.size());

マップはkey-valueリレーションであることに注意してください。このため、 をキーStringとして使用し、をとして使用するのではなく、 を使用することもできます。このように、3 つの異なる文字列を追加すると、それぞれに異なるハッシュ値 (ハッシュコード) が設定されます。したがって、 には 3 つの異なるキーがあります。ArrayListMap

次の点にも注意してください。

置く

public Object put(Object key, Object value) 指定された値をこのマップ内の指定されたキーに関連付けます。マップにこのキーのマッピングが以前に含まれていた場合、古い値は置き換えられます。

これが、同じオブジェクトを追加していたため、3 ではなく 1 を取得している理由ですnew ArrayList<String>()

Class HashMの仕様を詳しく見てみましょう 。

于 2013-02-12T05:26:22.580 に答える
1

ArrayList をキーとして使用し、試してください

    System.out.println(new ArrayList<String>().equals(new ArrayList<String>()));

それは印刷します

true
于 2013-02-12T05:27:33.053 に答える
0

最善の方法は、String オブジェクトをキーとして使用し、List を値として使用することです。

ここでJava ドキュメントの内容を参照してください

また、ArrayList をキーとして追加したい場合は、equals メソッドをオーバーライドするだけで十分です。

ここの投稿は良い洞察を提供します。その投稿から気に入ったものをいくつか入れました。

2 つの ArrayList の equals のオーバーライド:

 public boolean equals(List<String> one, List<String> two){
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}
于 2013-02-12T05:38:53.327 に答える
0

リストをキーとして、文字列を値として必要とする理由はわかりませんが、空のリストのハッシュコードは同じであるため、基本的に各 put 操作に同じ「キー」を使用しています。他の回答が言及しているように、リストを値として、文字列をキーとして切り替えるのがおそらく最善です。リストが変更された場合、今後 .get を試行すると null が返されます

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

出力

2
s2

のように新しいアイテムが追加されたとき

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");      
       bob.add("aabbcc");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

リストのハッシュが変更されているため、get は機能しません。この場合の出力は次のようになります。

2
null
于 2013-02-12T06:00:57.207 に答える