谁在将元素放入HashMap时调用类的equals方法?

use*_*466 6 java hashmap java-8

我是Java新手(非常新)。我试图了解HashMap和类的equals方法,以及它如何覆盖重复项。请参见以下代码:

public class Student {

    Integer StudentId;
    String Name;
    String City;

    public Student(Integer studentId, String name, String city) {
        super();
        StudentId = studentId;
        Name = name;
        City = city;
    }

    public Integer getStudentId() {
        return StudentId;
    }

    public String getName() {
        return Name;
    }

    public String getCity() {
        return City;
    }




    @Override
    public int hashCode() {
        System.out.println("haschode is called for " + this);

        final int prime = 31;
        int result = 1;
        result = prime * result + ((StudentId == null) ? 0 : StudentId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        System.out.println("equals is called for " + this);

        if (this == obj)
            return true;

        if (obj == null)
            return false;

        if (getClass() != obj.getClass())
            return false;

        Student other = (Student) obj;

        if (StudentId == null) {
            if (other.StudentId != null)
                return false;

        } else if (!StudentId.equals(other.StudentId))
            return false;

        return true;
    } 


    @Override
    public String toString() {
        return "\n Student [StudentId=" + StudentId + ", Name=" + Name + ", City=" + City + "] \n";
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub


         Map<Student, String> myMap = new HashMap<Student, String>();

         myMap.put(new Student(1, "andy", "p"), "Great");     //Line 1
         myMap.put(new Student(2, "sachin", "m"), "Better");
         myMap.put(new Student(3, "dev", "s"), "Good");
         myMap.put(new Student(1, "andy", "p"), "Excellent"); // Line 4

         System.out.println(myMap);


    }

}
Run Code Online (Sandbox Code Playgroud)

现在,仅当我编写再次放置相同键(即“第4行”)的代码时,用main()编写的代码才调用equals方法(请参见我的代码缩进)。

为什么没有为“第2行”和“第3行”调用equals方法?它应该为每条推杆线都要求等于....对吗?

我在这里缺少一些理解,并留有以下问题:(1)为什么每个看跌期权都不调用equals方法来检查类成员的相等性?(2)谁触发Student类equals方法的调用?

Zir*_*con 6

它应该为每条推杆线都要求等于....对吗?

否。HashMap equals仅在遇到现有键和中给定的键之间的哈希冲突后才会调用put

改写后,它hashCode首先调用以确定将密钥放入哪个“哈希存储桶”,如果目标存储桶中已存在密钥,则它将equals用于比较存储桶中的密钥是否相等。

由于的值Student.hashCode()仅基于ID,因此在插入期间,仅equals当映射遇到Student与插入的ID具有相同ID 的键时,才需要调用该映射。如果没有现有键与hashCode要插入的键相同,则无需调用equals

HashMap在插入期间非常有效。这也是为什么hashCode和之间存在契约的原因equals:如果两个对象定义相同equals,则它们也必须具有相同的含义hashCode(但不一定相反)。


dan*_*niu 5

equals()如果hashCode()结果不同,则不调用。它仅与1号线和4号线相同(学生ID为1),因此equals()被称为。

请注意,hashCode()对于两个不同的对象可能是相同的equals(),但是两个equals()对象绝不能有不同hashCode()

  • 如果根据equals(Object)方法,两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  • 根据equals(java.lang.Object)方法,如果两个对象不相等,则不需要在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

因此,最初不同的哈希码足以在equals()以后不调用。


Gho*_*ica 5

基于哈希的映射的全部目的是对哈希值进行操作(即为了提高效率)。

Map 首先关心的是不同的哈希值。因此,只要任何“传入”密钥具有(到目前为止)未知的哈希值,相等性并不重要。

仅当您遇到冲突的哈希时,传入的密钥实际上是不同的密钥还是相同的密钥才重要。在第一种情况下,您向映射添加一个新的键/值对,在第二种情况下,您使用潜在的新值更新已存储的键!

因此,调用equals()仅发生在 Map 实现必须决定具有相同哈希值的两个键是否相等的情况下。


Eri*_*rik 1

如果哈希码不同,则无需调用 equals。查看 HashMap() 的代码。如果哈希值相同,则调用 equals。