0

コード:

public static void main(String[] args) {
    Map<String,String> map= new HashMap<String,String>();
    map.put("a", "s");
    map.put("a", "v");

    System.out.println(map.get("a"));

}

さて、私の理解では、両方のputケースのキー値が同じであるため、つまりa、衝突が発生するため、連鎖が発生します。[間違っていたら訂正してください]。

key value にマップされたすべての値のリストを取得したい場合a、どうすれば取得できますか?

今は私のprintlnプリントvのみです。

4

10 に答える 10

4

これは、衝突連鎖aとは関係ありません。古い値を新しい値に置き換えています。

マップは一意のキーを保持します。特定のハッシュ関数に基づいて、 2 つの異なるキーがたまたま同じハッシュ値を取得すると、ハッシュ データ構造で衝突/連鎖が発生します。または Java では、 に対して同じ値を返すオブジェクトを明示的に作成できますhashCode()

キーに複数の値をマッピングする場合は、別のデータ構造/クラスを使用する必要があります。

于 2012-08-06T04:28:27.667 に答える
2

Java ドキュメントを参照してください。put

指定された値をこのマップ内の指定されたキーに関連付けます (オプションの操作)。マップに以前にキーのマッピングが含まれていた場合、古い値は指定された値に置き換えられます。(マップ m は、m.containsKey(k) が true を返す場合にのみ、キー k のマッピングを含むと言われます。)

衝突は、2つの同じキーではなく、2つの異なるキーが同じである場合に発生します。hashcode

class StringKey {
String text;

public StringKey() {
    text = "";
}

public StringKey(String text) {
    this.text = text;
}

public String getText() {
    return text;
}

public void setText(String text) {
    this.text = text;
}

@Override
public int hashCode() {
    if (text != null) {
        text.substring(0, 1).hashCode();
    }
    return 0;
}

@Override
public boolean equals(Object o) {
    if (o instanceof StringKey) {
        return ((StringKey) o).getText().equals(this.getText());
    }
    return false;
}

public static void main(String[] args) {
    Map<StringKey, String> map = new HashMap<StringKey, String>();
    StringKey key1 = new StringKey("a");
    StringKey key2 = new StringKey("b");

    map.put(key1, "s");
    map.put(key2, "v");

    System.out.println(map.get(key1));
    System.out.println(key1.hashCode() + " " + key2.hashCode() + " " + key1.equals(key2));
}
}

出力は

s
0 0 false

これでcollision;が発生します。ただし、マップ キーと値の出力からこれを解釈することはできません。

于 2012-08-06T04:28:57.573 に答える
2

他の人がすでに示唆したように、あなたのケースには衝突のようなものはありません。

これは単純に、Hashmap が一意のキーのみを受け入れるためです。

ただし、キーを一意にしない場合は、 Google Guava MultimapApache Multimapなどの代替手段を使用できます。

Google ライブラリを使用した例:

public class MutliMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();

// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");

// Getting the size
int size = myMultimap.size();
System.out.println(size);  // 4

// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]

Collection<string> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]

// Iterating over entire Mutlimap
for(String value : myMultimap.values()) {
 System.out.println(value);
}

// Removing a single value
myMultimap.remove("Fruits","Pear");
System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]

// Remove all values for a key
myMultimap.removeAll("Fruits");
System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
}
}
于 2012-08-06T04:33:19.030 に答える
1

HashMaps で使用されるハッシュ アルゴリズムは、最初はかなりあいまいです。内部的には、HashMap はインデックスを持つ配列に他なりません。ここでのインデックスは、通常「hashValue」と呼ばれます。hashValue は配列内の要素のインデックスであるため、HashMap 自体のサイズよりも小さくする必要があります。HashMap のハッシュ アルゴリズムは、キーのハッシュコードを hashValue に変換します。これは、マップがエントリ (キーと値のペア) を格納する場所です。

要素が Map に配置されると、要素キーのハッシュコードから hashValue が生成され、このインデックスの配列に Entry が格納されます。これは hashValue に他なりません。現在、ハッシュ アルゴリズムはある程度しか効率的ではありません。つまり、2 つの異なるキーに対して生成された hashValue が常に異なることを保証することはできません。2つの条件で同じになる可能性があります:1)キーは同じです(あなたの場合と同じです)2)キーは異なりますが、両方のキーに対して生成されたhashValueは同じです。

配列内の hashValue の位置にある Entry の値を置き換えることはできません。これは、非常に有効な 2 番目の条件に違反するためです。ここで equals() の出番です。ここで、HashMap は、新しいキーとそのインデックスのエントリに存在するキーが等しいかどうかをチェックします。両方のキーが同じ場合は置換を意味し、そうでない場合は衝突であり、HashMap は適切な衝突技術を使用します。

ここで、特定のキーに設定したすべての値のリストが必要な場合は、複合マップの使用を検討して HashMap<String, List<String>>ください。

于 2012-08-06T04:54:18.023 に答える
1

2 つ目は、最初に書いたput()ものを単純に上書きします。put()連鎖はありません。

于 2012-08-06T04:28:36.373 に答える
1

Secondputは first に置き換わるため、 Hashmapputのキー「a」を持つ値は 1 つだけになります。

したがって、マップには次のものが含まれます

map.put("a", "v");
于 2012-08-06T04:28:38.537 に答える
1

さて、私の理解によると、両方の put ケースのキー値は同じ、つまり a であるため、衝突は必然的に発生し、連鎖が発生します。[間違っていたら訂正してください]。

あなたが間違っている。それはマップの仕組みではありません。Google の Guava ライブラリのMultiMapの使用を検討してください。

いつでも自分でロールできます。

Map<String, ArrayList<String>>();
于 2012-08-06T04:30:14.157 に答える
1

HashMap次のように作成する必要があります

public static void main(String[] args) {
    HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
    if ( map.get("a") == null ){
        map.put("a", new ArrayList<String>());
    }

    ArrayList<String> innerList = map.get("a");
    innerList.add("s");
    innerList.add("v");

    map.put("a",innerList);

    System.out.println(map.get("a"));
}
于 2012-08-06T04:33:52.560 に答える
0

に入れようとしたキーは両方ともHashMap同じHashCodeです。したがって、最初の値が上書きされ、HashMap.

hashCode()メソッドをオーバーライドすることで、2 つの類似オブジェクトを同じ HashMap に配置できます。

于 2012-08-06T05:12:42.323 に答える