2011-08-10 36 views
0

JavaのHashMapの実装では、衝突を処理する値のリストを指し示す「バケット」を使用しており、オブジェクトのキーはhashCode()オブジェクトのequals()は、追加されるオブジェクトとそれが衝突するオブジェクトの両方で同じです。Java HashMapの衝突の例が正しくありません

私はHashMapを使って動作していましたが、何をするにしても、常にオーバーライドしているようです。

私はここで間違っています(私は意図的にhashCodeとequalsメソッドから "count"を残しました)。

public class HashMapTest { 

public static void main(String[] args) { 
    HashMapTest test = new HashMapTest(); 
    test.execute(); 
} 

public void execute() { 
    HashMap<String, Node> nodeMap = new HashMap<String, Node>(); 
    Node node1 = new Node("data1", 1); 
    Node node2 = new Node("data2", 2); 

    String key = "1"; 

    System.out.println("node1 hash: " + node1.hashCode()); 
    System.out.println("node2 hash: " + node2.hashCode()); 
    System.out.println("node1 hash == node2 hash? " + (node1.hashCode() == node2.hashCode() ? "true" : "false")); 
    System.out.println("node1.equals(node2)? " + (node1.equals(node2) ? "true" : "false")); 

    nodeMap.put(key, node1); 
    System.out.println("added node1 to hash map"); 
    System.out.println("hash map size: " + nodeMap.size()); 
    System.out.println("hash map entry set size: " + nodeMap.entrySet().size()); 
    System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false")); 
    System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false")); 

    nodeMap.put(key, node2); 
    System.out.println("added node2 to hash map"); 
    System.out.println("hash map size: " + nodeMap.size()); 
    System.out.println("hash map entry set size: " + nodeMap.entrySet().size()); 
    System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false")); 
    System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false")); 
} 

protected class Node { 

    private String data; 

    private Integer count; 

    public Node(String data, Integer count) { 
     this.data = data; 
     this.count = count; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + ((data == null) ? 0 : data.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Node other = (Node) obj; 
     if (data == null) { 
      if (other.data != null) 
       return false; 
     } 
     else 
      if (!data.equals(other.data)) 
       return false; 
     return true; 
    } 


    public String getData() { 
     return data; 
    } 


    public void setData(String data) { 
     this.data = data; 
    } 


    public Integer getCount() { 
     return count; 
    } 


    public void setCount(Integer count) { 
     this.count = count; 
    } 

} 

}

これは出力:

node1 hash: 95356390 
node2 hash: 95356391 
node1 hash == node2 hash? false 
node1.equals(node2)? false 
added node1 to hash map 
hash map size: 1 
hash map entry set size: 1 
hash map contains node1? true 
hash map contains node2? false 
added node2 to hash map 
hash map size: 1 
hash map entry set size: 1 
hash map contains node1? false 
hash map contains node2? true 
+0

ところで、 'hashCode'メソッドを' return data!= null? 'に単純化することができます。 data.hashCode():0; '1を加えて31を掛ける必要はありません。 –

答えて

3

ハッシュマップのキーは値がないハッシュされます。あなたのケースでは、put(key, node)を呼び出していて、キーは一定ですので、2番目のputが最初を上書きします。ノードがキーの場合、2つのエントリがあります。

2

値ではなくキーを確認する必要があります。

1

あなたがjavadoc for HashMapを読めば

プット(オブジェクトキー、オブジェクト値)

アソシエイツは、この中に指定されたキーに、指定された値を次のように、あなたはput()メソッドが定義されていることに注意しましょう地図。

put()を同じキーで2回呼び出すと、そのキーに関連付けられた元の値が上書きされます。

さらに、このテーブルでは、値ではなくキーのハッシュを使用して、適切なバケットを見つけます。

それ以外は、クラスの理解が正しいです。

ただし、パブリックAPIからの衝突は、クラス内で処理される可能性が高いため、表示できないと思います。

+0

これは意味があります。HashMap を使用するように変更し、hashCode()メソッドとequals()メソッドを変更して衝突を取得し、キーのhashCode()にマップされたバケット内のリストを構築することができます。しかし、put(K、V)に渡されたキーが別のキーと等しい()の場合、値が上書きされることに気付きました。私はバケツを識別するためにhashCode()を使用し、そこからの値に対してequal()を使用したと考えました。どうやら、キーequal()が別のキーであれば、それは関連する値を置き換えます。 質問に答えるために8時間の制限を超えたら、この区別を強調するコードを投稿します。 – Caleb

+0

バケットを識別するために 'hashCode()'を使用し、キーに対して 'equal()'メソッドを使用します。値が正常に取得されるまでは、キーに関連付けられている値は何であるかわからないため、値に対して 'equal()'メソッドを使用できませんでした。 'HashMap'のポイントは、キーと値の1対1のマッピングを持つことです。単一のキーを複数の値にマップすると、すべてを取り出すことができないため、非常に効果的なマップにはなりません値の! – ty1824

0

ここには、HashMap <ノード、ノード>を使用する更新されたコードがあります。また、equals()メソッドをcountフィールドをインクルードするように変更しましたが、hashCode()メソッドから除外しました。これが成功し、衝突を作成し、デバッガでのHashMapを見れば、あなたはそれが衝突していたバケツに構築されたリストを見ることができます:

public class HashMapTest { 

public static void main(String[] args) { 
    HashMapTest test = new HashMapTest(); 
    test.execute(); 
} 

public void execute() { 
    HashMap<Node, Node> nodeMap = new HashMap<Node, Node>(); 
    Node node1 = new Node("data1", 1); 
    Node node2 = new Node("data2", 2); 
    Node node3 = new Node("data1", 2); 
    Node node4 = new Node("data1", 1); 

    System.out.println("node1 hash: " + node1.hashCode()); 
    System.out.println("node2 hash: " + node2.hashCode()); 
    System.out.println("node3 hash: " + node3.hashCode()); 
    System.out.println("node1 hash == node2 hash? " + (node1.hashCode() == node2.hashCode() ? "true" : "false")); 
    System.out.println("node2 hash == node3 hash? " + (node2.hashCode() == node3.hashCode() ? "true" : "false")); 
    System.out.println("node1 hash == node3 hash? " + (node1.hashCode() == node3.hashCode() ? "true" : "false")); 
    System.out.println("node1.equals(node2)? " + (node1.equals(node2) ? "true" : "false")); 
    System.out.println("node2.equals(node3)? " + (node2.equals(node3) ? "true" : "false")); 
    System.out.println("node1.equals(node3)? " + (node1.equals(node3) ? "true" : "false")); 
    System.out.println(""); 

    nodeMap.put(node1, node1); 
    System.out.println("added node1 to hash map"); 
    System.out.println("hash map size: " + nodeMap.size()); 
    System.out.println("hash map entry set size: " + nodeMap.entrySet().size()); 
    System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false")); 
    System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false")); 
    System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false")); 
    System.out.println("node1's count from map: " + nodeMap.get(node1).getCount()); 
    System.out.println(""); 

    nodeMap.put(node2, node2); 
    System.out.println("added node2 to hash map"); 
    System.out.println("hash map size: " + nodeMap.size()); 
    System.out.println("hash map entry set size: " + nodeMap.entrySet().size()); 
    System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false")); 
    System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false")); 
    System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false")); 
    System.out.println("node1's count from map: " + nodeMap.get(node1).getCount()); 
    System.out.println(""); 

    // note that if node4 is used then it replaces the value that stored node1 
    nodeMap.put(node3, node3); 
    System.out.println("added node3 to hash map"); 
    System.out.println("hash map size: " + nodeMap.size()); 
    System.out.println("hash map entry set size: " + nodeMap.entrySet().size()); 
    System.out.println("hash map contains node1? " + (nodeMap.containsValue(node1) ? "true" : "false")); 
    System.out.println("hash map contains node2? " + (nodeMap.containsValue(node2) ? "true" : "false")); 
    System.out.println("hash map contains node3? " + (nodeMap.containsValue(node3) ? "true" : "false")); 
    System.out.println("node1's count from map: " + nodeMap.get(node1).getCount()); 
} 

protected class Node { 

    private String data; 

    private Integer count; 

    public Node(String data, Integer count) { 
     this.data = data; 
     this.count = count; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + getOuterType().hashCode(); 
     result = prime * result + ((data == null) ? 0 : data.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Node other = (Node) obj; 
     if (!getOuterType().equals(other.getOuterType())) 
      return false; 
     if (count == null) { 
      if (other.count != null) 
       return false; 
     } 
     else 
      if (!count.equals(other.count)) 
       return false; 
     if (data == null) { 
      if (other.data != null) 
       return false; 
     } 
     else 
      if (!data.equals(other.data)) 
       return false; 
     return true; 
    } 


    public String getData() { 
     return data; 
    } 


    public void setData(String data) { 
     this.data = data; 
    } 


    public Integer getCount() { 
     return count; 
    } 


    public void setCount(Integer count) { 
     this.count = count; 
    } 

    private HashMapTest getOuterType() { 
     return HashMapTest.this; 
    } 

} 

}

それは出力:

node1 hash: 1077170390 
node2 hash: 1077170391 
node3 hash: 1077170390 
node1 hash == node2 hash? false 
node2 hash == node3 hash? false 
node1 hash == node3 hash? true 
node1.equals(node2)? false 
node2.equals(node3)? false 
node1.equals(node3)? false 

added node1 to hash map 
hash map size: 1 
hash map entry set size: 1 
hash map contains node1? true 
hash map contains node2? false 
hash map contains node3? false 
node1's count from map: 1 

added node2 to hash map 
hash map size: 2 
hash map entry set size: 2 
hash map contains node1? true 
hash map contains node2? true 
hash map contains node3? false 
node1's count from map: 1 

added node3 to hash map 
hash map size: 3 
hash map entry set size: 3 
hash map contains node1? true 
hash map contains node2? true 
hash map contains node3? true 
node1's count from map: 1 
関連する問題