修改HashMap密钥之一

时间:2014-06-10 19:08:29

标签: java dictionary hashmap

package always.confusing;

import java.util.HashMap;
import java.util.Map;

class Dog {
public Dog(String n) { name = n; }
public String name;
public boolean equals(Object o) {
    if((o instanceof Dog) &&
            (((Dog)o).name == name)) {
        return true;
    } else {
        return false;
    }
}
public int hashCode() {return name.length(); }
}

public class QustionToaAsk {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Map<Object, Object> m = new HashMap<Object, Object>();

    Dog d1 = new Dog("clover");
    m.put(d1, "Dog key");

    System.out.println("**" + m.get(new Dog("clover")));

    d1.name = "magnolia";
    System.out.println("state after magnolia");
    System.out.println(m.get(new Dog("magnolia")));
    System.out.println(m.get(d1)); // #1
    System.out.println("**" + m.get(new Dog("clover")));///????????
    System.out.println("size:" + m.size());

    d1.name = "clover";
    System.out.println("\nstate after clover");
    System.out.println(m.get(new Dog("clover"))); // #2
    System.out.println(m.get(d1));
    System.out.println("size:" + m.size());

    d1.name = "arthur";
    System.out.println("\nstate after arthur");
    System.out.println(m.get(new Dog("arthur")));
    System.out.println(m.get(d1));
    System.out.println("size:" + m.size());
}

}

O / P:

**Dog key
玉兰之后的状态

null

null

**null

size:1

三叶草后的状态

Dog key

Dog key

size:1

亚瑟后的状态

Dog key

Dog key

size:1

为什么第一组打印无法获取具有三叶草和玉兰花内容的Dog对象 但在其他两组中,它是否按预期进行?

即为什么在尝试改为“玉兰花”之后,为什么接下来得到()(仍然使用适当的对象即获得(新的狗(“三叶草”)))))无法获取值“狗钥匙”?在改为等于...之后仍然是相同的输出 -

//忽略

3 个答案:

答案 0 :(得分:3)

您需要了解HashMap的工作原理。

当您将密钥放入包含N个桶的HashMap中时,密钥的hashCode用于查找适当的桶。然后使用equals()和添加的密钥比较存储桶中包含的每个密钥,以了解密钥是否已经存在于地图中。

类似地,当获取键的值时,首先使用hashCode()来查找适当的存储桶,然后将此存储桶中的每个键与equals()进行比较,传递给传递给get()的键。

您正在做两件使用HashMaps时不应该做的事情:

  1. 将密钥存储在地图中后修改密钥。这会修改其hashCode,并导致在相应的存储桶中不搜索该键。有点像你把所有的红色硬币放在一个红色的抽屉里,然后将其中一个键重新涂成蓝色。显然,如果你然后搜索蓝色硬币,你将在蓝色抽屉中搜索它们,而不是在存储它的红色抽屉中搜索它们,因为它最初是红色的。
  2. 使用一种算法实现hashCode(),使许多键具有相同的值。这是&#34; clover&#34;的情况。和#34; arthur&#34;,它们具有相同的长度,因此给出了相同的hashCode()给出了你的实现。 &#34;玉兰花&#34;,另一方面,没有相同的hashCode()。
  3. 鉴于上述情况,您应该能够理解代码的工作方式。只需绘制每项操作在纸上发生的事情,您就会明白。

答案 1 :(得分:1)

我强烈建议您先阅读how hashmap works in java

这里有很多问题。

  1. 当您调用m.put(d1, "Dog key");时,将计算hashCode,并确定将存储对象的hashMap中的存储区。在这种情况下,hashCode值为6。
  2. 然后您将名称更改为magnolia(因此hashCode更改为8)。 HashMap尝试搜索匹配对象,但是基于hashCode,它发现存储在bucket中的对象与hashCode value = 8相对应。
  3. 然后你将名称改回clover,长话短说,可以找到对象。
  4. 然后您将名称更改为arthur。 hashCode再次为6,HashMap设法找到正确的存储桶并使用equals方法 - 找到对象。
  5. 详细了解hashCodeequalshttp://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29

    顺便说一句您应该使用equals方法来比较字符串(阅读http://www.javapractices.com/topic/TopicAction.do?Id=18)。

答案 2 :(得分:-1)

第一:你想做什么?

第二: equals()是第一个问题,因为它只比较引用。见Here

第三:缺少hashCode()的{​​{1}}函数。您不应只覆盖dogequals()中的一个,请参阅Here