Java 为什么在定义hashCode()和equals()之后,我的代码仍然比较链接

Java 为什么在定义hashCode()和equals()之后,我的代码仍然比较链接,java,equals,hashcode,Java,Equals,Hashcode,我有两个班,学生和小组。这个小组有一组学生hashCode()和equals()都被覆盖 然后我在组中填充Set。为什么两个相同的组(相同的id、名称、Set等)不同?当我从组的hashCode()和equals()中删除Set时,组变得相同。但这是两个相同的集合。我假设在Set的情况下,它会比较链接。我不理解这一点,例如,String name是一个对象,Set是一个对象。当我同时包括tohashCode()和equals()时,它会比较字符串名的实际值和集合的链接 Student.java:

我有两个班,学生和小组。这个小组有一组学生
hashCode()
equals()
都被覆盖

然后我在组中填充
Set
。为什么两个相同的组(相同的id、名称、
Set
等)不同?当我从组的
hashCode()
equals()
中删除
Set
时,组变得相同。但这是两个相同的
集合
。我假设在
Set
的情况下,它会比较链接。我不理解这一点,例如,
String name
是一个对象,
Set
是一个
对象
。当我同时包括to
hashCode()
equals()
时,它会比较
字符串名的实际值和
集合的链接

Student.java:

public class Student {  

    private int id;
    private String firstName;
    private String lastName;

    public Student(int id, String firstName, String lastName) {     
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }   

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    @Override
    public boolean equals(final Object other) {
        if (this == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!getClass().equals(other.getClass())) {
            return false;
        }
        Student castOther = (Student) other;
        return Objects.equals(id, castOther.id) 
                && Objects.equals(firstName, castOther.firstName)
                && Objects.equals(lastName, castOther.lastName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, firstName, lastName);
    }       
}
public class Group {

    private int id;
    private String name;    
    private Set<Student> students;

    public Group(int id, String name) {     
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(final Object other) {
        if (this == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!getClass().equals(other.getClass())) {
            return false;
        }
        Group castOther = (Group) other;
        return Objects.equals(id, castOther.id) 
                && Objects.equals(name, castOther.name)
                && Objects.equals(students, castOther.students);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, students);
    }
}
Set<Group> retrieveAll() throws DaoException {      
    String sql = "select * from groups;";               
    Set<Group> groupSet = new HashSet<>();

    try (Connection connection = daoFactory.getConnection();
            PreparedStatement preparedStatement = 
            connection.prepareStatement(sql)) {         
        preparedStatement.execute();
        ResultSet resultSet = preparedStatement.getResultSet();         

        while (resultSet.next()) {
            int id = resultSet.getInt("group_id");
            String name = resultSet.getString("name");              
            Group group = new Group(id, name);              
            group.setStudents(studentDao.retrieveByGroupId(id));                
            groupSet.add(group);
        }                       
    } catch (Exception e) {         
        throw new DaoException(e);          
    } 
    return groupSet;
}
Set<Student> retrieveByGroupId(int groupId) throws DaoException {       
    String sql = "select * from student where group_id = ?;";       
    Set<Student> studentSet = new HashSet<>();

    try (Connection connection = daoFactory.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
        preparedStatement.setInt(1, groupId);
        preparedStatement.execute();            
        ResultSet resultSet = preparedStatement.getResultSet();

        while (resultSet.next()) {
            int id = resultSet.getInt("student_id");
            String firstName = resultSet.getString("first_name");
            String lastName = resultSet.getString("last_name");             
            Student student = new Student(id, firstName, lastName);             
            studentSet.add(student);
        }                       
    } catch (Exception e) {
        throw new DaoException(e);          
    } 
    return studentSet;
}
public class GroupDaoImplTest {

private GroupDaoImpl groupDao = new GroupDaoImpl();
private static Set<Group> groupSet = new HashSet<>();
private static Group group;

@BeforeClass
public static void setUp() throws DaoException {
    StudentDaoImpl studentDao = new StudentDaoImpl();
    group = new Group(1, "Group 11");
    group.setStudents(studentDao.retrieveByGroupId(1));
    groupSet.add(group);        
    groupSet.add(new Group(2, "Group 12")); 
}

@Test
public void testInsert() throws DaoException {
    groupDao.insert(new Group(1, "Group 13"), 2);       
}

@Test
public void testUpdate() throws DaoException {
    groupDao.update(new Group(15, "Group 11"));     
}

@Test
public void testDelete() throws DaoException {
    groupDao.delete(new Group(16, "Group 11"));
}

@Test
public void testRetrieve() throws DaoException {        
    assertThat(groupDao.retrieve(1), is(group));        
}

@Test
public void testRetrieveByCathedraId() throws DaoException {        
    assertThat(groupDao.retrieveByCathedraId(1), is(groupSet));
}

@Test
public void testRetrieveAll() throws DaoException {             
    assertThat(groupDao.retrieveAll(), is(groupSet));
}
Group.java:

public class Student {  

    private int id;
    private String firstName;
    private String lastName;

    public Student(int id, String firstName, String lastName) {     
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }   

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    @Override
    public boolean equals(final Object other) {
        if (this == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!getClass().equals(other.getClass())) {
            return false;
        }
        Student castOther = (Student) other;
        return Objects.equals(id, castOther.id) 
                && Objects.equals(firstName, castOther.firstName)
                && Objects.equals(lastName, castOther.lastName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, firstName, lastName);
    }       
}
public class Group {

    private int id;
    private String name;    
    private Set<Student> students;

    public Group(int id, String name) {     
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(final Object other) {
        if (this == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!getClass().equals(other.getClass())) {
            return false;
        }
        Group castOther = (Group) other;
        return Objects.equals(id, castOther.id) 
                && Objects.equals(name, castOther.name)
                && Objects.equals(students, castOther.students);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, students);
    }
}
Set<Group> retrieveAll() throws DaoException {      
    String sql = "select * from groups;";               
    Set<Group> groupSet = new HashSet<>();

    try (Connection connection = daoFactory.getConnection();
            PreparedStatement preparedStatement = 
            connection.prepareStatement(sql)) {         
        preparedStatement.execute();
        ResultSet resultSet = preparedStatement.getResultSet();         

        while (resultSet.next()) {
            int id = resultSet.getInt("group_id");
            String name = resultSet.getString("name");              
            Group group = new Group(id, name);              
            group.setStudents(studentDao.retrieveByGroupId(id));                
            groupSet.add(group);
        }                       
    } catch (Exception e) {         
        throw new DaoException(e);          
    } 
    return groupSet;
}
Set<Student> retrieveByGroupId(int groupId) throws DaoException {       
    String sql = "select * from student where group_id = ?;";       
    Set<Student> studentSet = new HashSet<>();

    try (Connection connection = daoFactory.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
        preparedStatement.setInt(1, groupId);
        preparedStatement.execute();            
        ResultSet resultSet = preparedStatement.getResultSet();

        while (resultSet.next()) {
            int id = resultSet.getInt("student_id");
            String firstName = resultSet.getString("first_name");
            String lastName = resultSet.getString("last_name");             
            Student student = new Student(id, firstName, lastName);             
            studentSet.add(student);
        }                       
    } catch (Exception e) {
        throw new DaoException(e);          
    } 
    return studentSet;
}
public class GroupDaoImplTest {

private GroupDaoImpl groupDao = new GroupDaoImpl();
private static Set<Group> groupSet = new HashSet<>();
private static Group group;

@BeforeClass
public static void setUp() throws DaoException {
    StudentDaoImpl studentDao = new StudentDaoImpl();
    group = new Group(1, "Group 11");
    group.setStudents(studentDao.retrieveByGroupId(1));
    groupSet.add(group);        
    groupSet.add(new Group(2, "Group 12")); 
}

@Test
public void testInsert() throws DaoException {
    groupDao.insert(new Group(1, "Group 13"), 2);       
}

@Test
public void testUpdate() throws DaoException {
    groupDao.update(new Group(15, "Group 11"));     
}

@Test
public void testDelete() throws DaoException {
    groupDao.delete(new Group(16, "Group 11"));
}

@Test
public void testRetrieve() throws DaoException {        
    assertThat(groupDao.retrieve(1), is(group));        
}

@Test
public void testRetrieveByCathedraId() throws DaoException {        
    assertThat(groupDao.retrieveByCathedraId(1), is(groupSet));
}

@Test
public void testRetrieveAll() throws DaoException {             
    assertThat(groupDao.retrieveAll(), is(groupSet));
}
我觉得它很好用:

Group g1 = new Group(1, "a");
Set<Student> s1 = new HashSet<>();
s1.add(new Student(1, "a", "b"));
g1.setStudents(s1);

Group g2 = new Group(1, "a");
Set<Student> s2 = new HashSet<>();
s2.add(new Student(1, "a", "b"));
g2.setStudents(s2);

System.out.println(g1.equals(g2));
g1组=新组(1,“a”);
Set s1=新的HashSet();
s1.加入(新学生(1,“a”、“b”);
g1.学生(s1);
g2组=新组(1,“a”);
Set s2=新的HashSet();
s2.加入(新学生(1,“a”、“b”);
g2.设置学生(s2);
System.out.println(g1.equals(g2));
我觉得它很好用:

Group g1 = new Group(1, "a");
Set<Student> s1 = new HashSet<>();
s1.add(new Student(1, "a", "b"));
g1.setStudents(s1);

Group g2 = new Group(1, "a");
Set<Student> s2 = new HashSet<>();
s2.add(new Student(1, "a", "b"));
g2.setStudents(s2);

System.out.println(g1.equals(g2));
g1组=新组(1,“a”);
Set s1=新的HashSet();
s1.加入(新学生(1,“a”、“b”);
g1.学生(s1);
g2组=新组(1,“a”);
Set s2=新的HashSet();
s2.加入(新学生(1,“a”、“b”);
g2.设置学生(s2);
System.out.println(g1.equals(g2));

调用 对象。相等(学生,其他。学生)


我猜,只有当两个组实例的students字段都引用Set的一个实例时,才会返回true

调用 对象。相等(学生,其他。学生)


我猜,只有当两个组实例的students字段都引用Set的一个实例时,才会返回true

我认为问题在于,您的测试类中
学生
字段为
null
,而
groupDao.retrieveAll()
返回的组的
学生
字段始终设置为非null。如果组中没有学生,则其
students
字段为空(不包含学生),不为空


Objects.hash()
为空字段提供哈希代码0,空集的哈希代码也为0。因此,这两个组具有相同的哈希代码,但它们并不相等。

我认为问题在于测试类中
group
students
字段是
null
,而
groupDao.retrieveAll()返回的组的
students
字段
始终具有非空的
学生集。如果组中没有学生,则其
students
字段为空(不包含学生),不为空


Objects.hash()
为空字段提供哈希代码0,空集的哈希代码也为0。因此,这两个组具有相同的哈希代码,但它们并不相等。

您能展示构建您正在比较的两个组的代码吗?@EJP只是想知道您从哪里获得了这么高的声誉!你说的“链接”是什么意思?你的意思是引用吗?DodgyCodeException yesEran添加你需要的代码,你可以展示构建你正在比较的两个组的代码吗?@EJP只是想知道你从哪里得到这么多声誉!你说的“链接”是什么意思?你是指引用吗?DodgyCodeException Yesseran添加你要求的代码,为了使你的代码工作,你应该检查学生的集合并比较他们是否相等,而不是做对象。equals(学生,castOther.students)不,Objects。equals(a,b)最终调用a.equals(b),对于集合,每个元素调用equals。因此,要使代码正常工作,您应该遍历学生集,比较所有学生是否相等,而不是进行对象比较。equals(students,castOther.students)No,Objects。equals(a,b)最终调用a.equals(b),对于集合,每个元素都调用equals。@shmosel不管名称如何,
HashSet
s都会检查对象相等性。他们使用散列代码将元素放入存储桶中,但在每个存储桶中,他们调用
equals()
来确定元素是否相等。这就是我的问题。@shmosel-Aha,我想我误解了你的话:-)。关于问题中的错误消息,我注意到的第一件事是,两个集合都包含具有相同哈希代码的组(
Object.toString()
返回表单的字符串)class@hashcode),这就导致了我的一个初步假设,即物体实际上是相等的,问题一定在别处。我现在认为这个假设是错误的。所以hash-code注释是为了解释这一点,以防其他人注意到同样的事情。@shmosel尽管有名称,
HashSet
s检查对象是否相等。他们使用散列代码将元素放入存储桶中,但在每个存储桶中,他们调用
equals()
来确定元素是否相等。这就是我的问题。@shmosel-Aha,我想我误解了你的话:-)。关于问题中的错误消息,我注意到的第一件事是,两个集合都包含具有相同哈希代码的组(
Object.toString()
返回表单的字符串)class@hashcode),这就导致了我的一个初步假设,即物体实际上是相等的,问题一定在别处。我现在认为这个假设是错误的。因此,散列码注释是为了解释这一点,以防其他人注意到同样的事情。