Java 当我重写hashcode并从hashmap获取值时,为什么必须重写equals

Java 当我重写hashcode并从hashmap获取值时,为什么必须重写equals,java,hashmap,equals,hashcode,Java,Hashmap,Equals,Hashcode,当我只重写hashCode()函数和comment equalas()方法时,我会得到以下输出: public class DemoHashSet { private String name; private String dob; private String gender; public DemoHashSet(String name, String dob, String gender) { super(); this.name = name; this.dob

当我只重写hashCode()函数和comment equalas()方法时,我会得到以下输出:

public class DemoHashSet {
private String name;
private String dob;
private String gender;

public DemoHashSet(String name, String dob, String gender) {
    super();
    this.name = name;
    this.dob = dob;
    this.gender = gender;
}

public String getName() {
    return name;
}

public String getDob() {
    return dob;
}

public String getGender() {
    return gender;
}

@Override
public String toString() {
    return name+" "+dob+" "+gender;
}

@Override
public boolean equals(Object o) {
    return this.name.equals(((DemoHashSet)o).getName());
}

@Override
public int hashCode() {
    int code = this.name.hashCode() + this.dob.hashCode() + gender.hashCode();
    System.out.println("Hash Code: "+code);
    return code;
}

public static void main(String args[]) throws ParseException {

    Map<DemoHashSet, String> hmap = new HashMap<DemoHashSet, String>();

    DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
    DemoHashSet obj2 = new DemoHashSet("key2", "122990", "male");
    DemoHashSet obj3 = new DemoHashSet("key3", "123990", "male");
    DemoHashSet obj4 = new DemoHashSet("key4", "124990", "male");
    DemoHashSet obj5 = new DemoHashSet("key5", "125990", "male");

    hmap.put(obj1, "value1");
    hmap.put(obj2, "value2");
    hmap.put(obj3, "value3");
    hmap.put(obj4, "value4");
    hmap.put(obj5, "value5");

    System.out.println("Get values: ");
    System.out.println(hmap.get(new DemoHashSet("key1", "121990", "male")));
    System.out.println(hmap.get(new DemoHashSet("key2", "122990", "male")));
}
}
需要解释此行为,因为在两种情况下计算的哈希代码相同,但在第二种情况下,它给出null

hadCode()函数的作用是通过导出特定段/桶的对象键,将对象存储在特定段/桶中。要理解此方法的用途,您需要了解HashTable或HashMap在内部是如何工作的。维基百科是了解它的最佳来源

equals()函数用于检查集合对象中是否存在特定对象

如果两个对象相等,hasCode将相同,但反之则不正确。两个不同的对象可以具有相同的哈希代码

hadCode()函数的作用是通过导出特定段/桶的对象键,将对象存储在特定段/桶中。要理解此方法的用途,您需要了解HashTable或HashMap在内部是如何工作的。维基百科是了解它的最佳来源

equals()函数用于检查集合对象中是否存在特定对象

如果两个对象相等,hasCode将相同,但反之则不正确。两个不同的对象可以具有相同的哈希代码


需要对这种行为进行解释
这正是我所期望的行为。为什么?
hascode有一点是不能100%保证唯一对象的唯一性。这意味着在某些情况下 不同的对象可以有相似的hascode

HashMap实现将这一点牢记在心。因此,当您传递一个键时,它们总是比较
hascode
,然后检查相等性(参考检查然后是
equals()
方法)。如果未找到任何内容,则返回
null
。您可以检查源代码:

Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values: 
Hash Code: 1457153183
null
Hash Code: 1457182975
null
此代码块表示:

  • hash
    (hascode)对于给定的键和条目键都需要相同

  • 给定的键和输入键需要是相同的对象(相同的引用)它们需要通过
    equals()
    方法相等
在您的例子中,当您注释equals方法时,将使用来自超类的equals()方法的默认实现,它实际上只检查引用的相等性(我猜是这样)。所以

if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
后来

DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
不引用同一对象,因此
equals()
return false和
get()
return
null
未找到与键匹配的项。
当您的
equals()
方法根据您的实现而存在时,您告诉这些对象是相等的,因为它们具有相同的名称


哈希代码不能保证且不相等。需要解释此行为。
这正是我所期望的行为。为什么?
hascode有一点是不能100%保证唯一对象的唯一性。这意味着在某些情况下 不同的对象可以有相似的hascode

HashMap实现将这一点牢记在心。因此,当您传递一个键时,它们总是比较
hascode
,然后检查相等性(参考检查然后是
equals()
方法)。如果未找到任何内容,则返回
null
。您可以检查源代码:

Hash Code: 1457153183
Hash Code: 1457182975
Hash Code: 1457212767
Hash Code: 1457242559
Hash Code: 1457272351
Get values: 
Hash Code: 1457153183
null
Hash Code: 1457182975
null
此代码块表示:

  • hash
    (hascode)对于给定的键和条目键都需要相同

  • 给定的键和输入键需要是相同的对象(相同的引用)它们需要通过
    equals()
    方法相等
在您的例子中,当您注释equals方法时,将使用来自超类的equals()方法的默认实现,它实际上只检查引用的相等性(我猜是这样)。所以

if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
后来

DemoHashSet obj1 = new DemoHashSet("key1", "121990", "male");
不引用同一对象,因此
equals()
return false和
get()
return
null
未找到与键匹配的项。
当您的
equals()
方法根据您的实现而存在时,您告诉这些对象是相等的,因为它们具有相同的名称


hashcode不能保证并且不是相等的。您使用的是
HashMap
。在内部,
HashMap
有许多bucket,每个bucket都有一个存储项的列表

无论何时调用
HashMap.get()
HashMap
都将调用
DemoHashSet.hashCode()
,并使用键参数(可能带有模数(
%
)运算符)来确定要查找的存储桶

然后,它将使用
DemoHashSet.equals()
方法搜索此列表,查看它是否可以匹配键参数。如果它
equals()
曾经返回
true
,则将返回该值,否则返回
null

从以下文件中:

注意,通常需要重写hashCode方法 每当重写此方法时,以保持 hashCode方法的契约,它声明必须有相等的对象 具有相等的散列码


您正在使用一个
HashMap
。在内部,
HashMap
有许多bucket,每个bucket都有一个存储项的列表

无论何时调用
HashMap.get()
HashMap
都将调用
DemoHashSet.hashCode()
,并使用键参数(可能带有模数(
%
)运算符)来确定要查找的存储桶

然后,它将使用
DemoHashSet.equals()
方法搜索此列表,查看它是否可以匹配键参数。如果它
equals()
曾经返回
true
,则将返回该值,否则
null<