使用HashSet与用户类Employee

3

我知道这可能是一个非常愚蠢的问题,但是在了解了关于HashSet的知识后,当我执行下面的代码时感到困惑。

我有一个如下的Employee类(只保留相关的代码片段):

public class Employee {
    //assume it has 3 variable name(String),salary(double) and id(int)
    //assume the constructor, getter-setters are there 

    //following is my equals and hashCode implementation
    public boolean equals(Employee e){
        return name.equals(e.name);
    }

    public int hashCode(){
        return id;
    }
}

现在我有以下使用HashSet的代码:

Employee e1  = new Employee("Abc", 2.0, 1);
Employee e2  = new Employee("abc", 3.0, 4);
Employee e3  = new Employee("XYZ", 4.0, 3);
Employee e4  = new Employee("Mno", 5.0, 2);
Employee e5  = new Employee("Abc", 77.0, 1);

Set<Employee> sEmp = new HashSet<Employee>();
sEmp.add(e1);
sEmp.add(e2);
sEmp.add(e3);
sEmp.add(e4);
sEmp.add(e5);

for(Employee e : sEmp){
    System.out.println(e);
}

所以我在控制台上打印出所有对象数据如下:
Abc 77.0 1
Abc 2.0 1
Mno 5.0 2
XYZ 4.0 3
abc 3.0 4

据我所知,集合不允许重复项,并且会在使用equals方法时检查重复性(如果我错了,请纠正我)。
另外,HashSet使用hashCode,因此在上述情况下,它不应该添加对象e5。但是它成功地将该元素添加到了集合中。这让我困惑不解。
(请忽略我是否遗漏了标准等所有内容,我正在尝试理解概念/实现)。 编辑:这可能听起来是一个愚蠢的问题,但我正在为认证做准备,想看看事情是如何工作的。

1
从Collection javadoc页面。 "实现可以自由地实现优化,从而避免等式调用,例如,通过首先比较两个元素的哈希码。" - Alexis C.
@ Abubakkar Rangara,你能提供Employee构造函数的代码吗? - M Sach
@MSach 这很简单,但我从下面得到了答案,这是我自己的愚蠢错误。 - Abubakkar
3个回答

8

您正在过载equals而不是覆盖它。 它的参数应该是Object类型。

但是您的hashCode正在检查id,而equals正在检查name。 它们可能应由相同的属性构建。


3
这是为什么我们应该在可能的情况下使用@Override注释的标准示例。
如果您将此注释与您的equals方法一起使用,编译器会通知您未覆盖equals方法,因为在超类中不存在equals(Employe)方法,但存在equals(Object)。所以您正在重载此方法(您正在创建具有不同参数的附加方法)。
因此,HashSet不使用您的equals方法的代码,而是使用从Object类继承的equals(Object)方法的代码,该方法仅检查引用相等性:
public boolean equals(Object obj) {
    return (this == obj);
}

0

我在equals方法中添加了一些代码。这将允许您更新员工ID的最新值。

package com.test.day16;

import java.util.HashSet;
import java.util.Set;

/**
 * 
 * @author PradeepPadmarajaiah
 *
 */
public class Employee {

    private int empId;
    private String empName;

    public Employee(int empId, String empName) {
        super();
        this.empId = empId;
        this.empName = empName;
    }

    /**
     * @return the empId
     */
    public final int getEmpId() {
        return empId;
    }

    /**
     * @param empId
     *            the empId to set
     */
    public final void setEmpId(int empId) {
        this.empId = empId;
    }

    /**
     * @return the empName
     */
    public final String getEmpName() {
        return empName;
    }

    /**
     * @param empName
     *            the empName to set
     */
    public final void setEmpName(String empName) {
        this.empName = empName;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "Employee [empId=" + empId + ", empName=" + empName + "]";
    }

    @Override
    public int hashCode() {
        return this.empId;
    }

    @Override
    public boolean equals(Object obj) {
        Employee employee = (Employee) obj;
        if (employee.empId == this.empId) {
            employee.setEmpName(this.empName);
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        Set<Employee> employees = new HashSet<>();
        employees.add(new Employee(1, "Raj"));
        employees.add(new Employee(1, "Pradeep"));
        employees.add(new Employee(1, "Kumar"));
        employees.add(new Employee(2, "Chandan"));
        employees.add(new Employee(2, "Amitava"));

        System.out.println(employees);
    }
}

请检查代码行 "employee.setEmpName(this.empName);",这将覆盖id的值。这意味着,empId 1将具有最新的empName值,即Kumar。 否则,empId 1将具有empName值,即Raj,这是首次分配的值,并且不会在检查后将其值覆盖为Kumar。 现在,这类似于HashMap机制。

代码结果将是 [Employee [empId=1, empName=Kumar],Employee [empId=2, empName=Amitava]]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接