import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
class Employee{
int id;
Employee(int id){
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int hashCode(){
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object obj){
return EqualsBuilder.reflectionEquals(this, obj);
}
}
public class P2 {
public static void main(String[] args) {
Employee emp1 = new Employee(10);
Employee emp2 = new Employee(10);
Employee emp3 = new Employee(14);
HashMap<Employee,String> emp = new HashMap();
emp.put(emp1, "Employee1");
emp.put(emp2, "Employee2");
emp.put(emp3, "Employee3");
Set set = emp.keySet();
Iterator it = set.iterator();
while(it.hasNext()){
Employee empl = (Employee)it.next();
System.out.println(emp.get(empl));
}
System.out.println(emp.containsKey(emp1));
System.out.println(emp1.equals(emp2));
System.out.println(emp.get(emp1));
}
}
输出: -
Employee2
Employee3
true
true
Employee2
此处EMP1和EMP2是相等的对象。第一2输出表示我们在哈希图中有2个条目(不是3个)。瞬间,我们将第二个对象(EMP2)插入哈希姆普中,它删除了先前的条目,即EMP1。但是第三次输出表示哈希图仍然包含关键EMP1和第五输出,表示关键EMP1和EMP2在哈希姆普中提到了相同的条目。我对Hashmap IE输入的这种行为感到困惑,但是键仍然存在并指的是下一个平等对象。
,因为emp1
和emp2
都具有相同的id
,即10,apache commons lib
将它们视为equal
和hashcode
也一样。因此,当您将EMP2放入hashmap中时,它实际上并没有为hashmap添加新密钥,它只是将"雇员"的现有值替换为"雇员2"。由于EMP1和EMP2是相同的,因此在Hashmap上调用contains()
方法时,您都将获得true。为了避免这种情况:
- 为您的员工分配不同的ID
- 向员工类添加更多属性
- 让Java本身决定哈希码,而不是使用Apache Commons lib。
我还可以补充说,而不是依靠空当的反射用法,而是应该使用它们提供的显式流利API。
- 基本上,hashmap使用key.hashcode()和key.equals()来定位该值,因此,如果两个对象hashcode()方法返回相同的值,而equals()也为true,那么他们将考虑相同钥匙。
- commons lang的ReflectionHashCode()和ReflectionEquals()基于对象字段以生成哈希码并等于结果。在您的情况下,由于EMP1和EMP2只有一个字段ID,并且它们具有相同的值10,因此RelfectionHashCode()将返回相同的值,并且如果比较EMP1和EMP2。>
基于上述两个点,EMP1和EMP2实际上是Hashmap观点中相同的键。因此,emp.get(emp1)和emp.get(emp2)将返回相同的值,即"雇员2"。