Java 覆盖hashmap中的equals问题

Java 覆盖hashmap中的equals问题,java,Java,我在重写equals方法时遇到了一些问题。以下是我的代码: import java.util.HashMap; import java.util.Map; public class HashCodeTest { public static void main(String[] args) { Employee emp1=new Employee(); emp1.setName("emp1"); Employee emp2=new Employee(); em

我在重写equals方法时遇到了一些问题。以下是我的代码:

import java.util.HashMap;
import java.util.Map;

public class HashCodeTest {

public static void main(String[] args) {
    Employee emp1=new Employee();
    emp1.setName("emp1");

    Employee emp2=new Employee();
    emp2.setName("emp2");

    Employee emp3=new Employee();
    emp3.setName("emp3");

    Map map=new HashMap<Employee,String>();
    System.out.println("put a");
    map.put(emp1, "a");
    System.out.println("put b");
    map.put(emp2, "b");
    System.out.println("put c");
    map.put(emp3, "c");

    System.out.println();
    System.out.println("map element are "+map);
    System.out.println("get 3rd obj");
    System.out.println("map element are "+map.get(emp3));
    System.out.println();

    System.out.println("get 2nd obj");
    System.out.println("map element are "+map.get(emp2));
}

}

class Employee 
{

.
.
getters and setters

@Override
public int hashCode()
{
System.out.println("hashcode called");
return 12;
}
@Override
public boolean equals(Object str)
{
System.out.println("equal called");
return false;
}
}
我已经重写了总是返回false的equals方法和总是返回相同值的hashcode方法。因此,根据这个原理,每个物体都会落在同一个桶上。但我的问题是,我无法理解当equals方法总是返回false时,为什么它能够给出与键匹配的正确输出


请帮忙。提前感谢。

如果查看
HashMap
实现,您会发现此方法执行实际查找:

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k)))) // !
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k)))) // !
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}
final节点getNode(int散列,对象键){
节点[]选项卡;节点第一,e;int n;K;
如果((tab=table)!=null&(n=tab.length)>0&&
(first=tab[(n-1)&散列]!=null){
如果(first.hash==hash&&//始终检查第一个节点
((k=first.key)==key | |(key!=null&&key.equals(k)))/!
先返回;
if((e=first.next)!=null){
if(树节点的第一个实例)
return((TreeNode)first).getTreeNode(hash,key);
做{
如果(e.hash==hash&&
((k=e.key)==key | |(key!=null&&key.equals(k)))/!
返回e;
}而((e=e.next)!=null);
}
}
返回null;
}

首先通过引用比较键(请参见
/!
),然后通过相等进行比较。因此,它返回正确的值,尽管您的
实现有缺陷,但它等于
实现

如果查看
HashMap
实现,您会发现此方法执行实际查找:

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k)))) // !
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k)))) // !
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}
final节点getNode(int散列,对象键){
节点[]选项卡;节点第一,e;int n;K;
如果((tab=table)!=null&(n=tab.length)>0&&
(first=tab[(n-1)&散列]!=null){
如果(first.hash==hash&&//始终检查第一个节点
((k=first.key)==key | |(key!=null&&key.equals(k)))/!
先返回;
if((e=first.next)!=null){
if(树节点的第一个实例)
return((TreeNode)first).getTreeNode(hash,key);
做{
如果(e.hash==hash&&
((k=e.key)==key | |(key!=null&&key.equals(k)))/!
返回e;
}而((e=e.next)!=null);
}
}
返回null;
}
首先通过引用比较键(请参见
/!
),然后通过相等进行比较。因此,它返回正确的值,尽管您的
实现有缺陷,但它等于
实现

试试这个-

员工emp2x=新员工(); emp2x.集合名(“emp2”)

System.out.println(“map元素是”+map.get(emp2x))

试试这个-

员工emp2x=新员工(); emp2x.集合名(“emp2”)


System.out.println(“map元素是”+map.get(emp2x))

hashmap首先检查引用相等,如果通过,则跳过.equals调用。这是一种优化,因为equals契约指定如果a==b,那么a.equals(b)。

hashmap首先检查引用的相等性,如果通过,则跳过.equals调用。这是一个优化,因为equals契约指定如果a==b,那么a.equals(b)。

我没有检查实现,但可能它在
a==b
时使用了一个快捷方式,并且没有调用
a.equals(b)
在本例中。我没有检查实现,但可能它在
a==b
时使用了快捷方式,在本例中不调用
a.equals(b)
。非常感谢。这是我认识的新事物。真的谢谢……非常感谢。这是我认识的新事物。真的谢谢。。