# equals()和hashCode() 基础知识学习

equals()和hashCode() 详细学习

  • Object类是每个类的父类,所有的对象实现了Object中定义的方法。equals()、hashCode()它们是java.lang.Object中的方法。

equals()

Object类中的equals()
public boolean equals(Object obj) {
    
    
    return (this == obj);
}

使用等号判断两个对象是否相等,对象在内存中的表现形式为标识(内存地址)、状态(数据)。

等号==equals()相等问题
  • 等号比较的是两个对象的内存地址是否相等。
  • equals()比较的是对象的内容是否相等。

例子1

String a = "123";
String b = "123";
System.out.println(a==b?"yes":"no");
  • a和b的创建方式,可能创建 一个对象也有可能不创建,如果赋值的字符串在java String池中不存在,会在String池中创建一个a="123"的对象,然后把a、b指向这个内存地址,之后用这种方式创建,始终只有一个地址被分配。

例子1中输出的结果应该是yes,因为a==b判断的是对象的地址是否相等,综合分析此时a和b的地址相等。

例2

String c = new String("123");
String d = new String( "123");
System.out.println(c==d?"yes":"no");
  • new String()至少会创建一个对象,也有可能创建两个,会在堆中创建一个c的对象,同时如果这个字符串在String池中不存在。会在String池中创建"123"这个对象。

例2中输出的结果是No,这和new String()有关。此时用==判断时候两个对象的地址不同,所以值为no.

String等类重写equals()
public boolean equals(Object anObject) {
    
    
    if (this == anObject) {
    
    
        return true;
    }
    if (anObject instanceof String) {
    
    
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
    
    
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
    
    
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

hashCode()

hashCode()方法给对象返回一个hash code值,这个方法被用于hash tables。

  • 如果根据equal(Object)方法是相等的,那么调用二者各自的hashCode()方法必须产生同一个int的结果。

  • 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

Object类中hashCode()方法的定义

public native int hashCode();
  • hashCode的存在主要用于查找的快捷性,如Hashtable、HashMap等,hashCode是用来在散列存储结构中确定对象存储地址的。

重写equals()和hashCode()

public class User {
    
    

    private int id;
    private String name;
    private String address;

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

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) {
    
    
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
    
    
            return false;
        }
        User user = (User) o;
        return id == user.id &&
                Objects.equals(name, user.name) &&
                Objects.equals(address, user.address);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(id, name, address);
    }
    
    // setget()省略
}

如果只重写equals()方法那么num为null。user指向的对象和map.get()中new 的对象是两个对象,他们的存储地址不同。

@Test
public void test1(){
    
    
    User user = new User(1,"张三","test1");
    System.out.printf(String.valueOf(user.hashCode()));

    HashMap<User,Integer> map = new HashMap<>(16);
    map.put(user,23);

    System.out.print("=======");
    Integer num = map.get(new User(1, "张三", "test1"));
    System.out.printf(String.valueOf(num));

}
HashMap的get()
  • get()方法,如果getNode()为Null 则get()返回null。
  • getNode()
    • hash是key的hash,形参key就是key
public V get(Object key) {
    
    
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

final Node<K,V> getNode(int hash, Object key) {
    
    
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    // 成员变量table不为空,且table的长度大于0,并且经过hash函数计算的存储单元不为空
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
    
    
        // 第一个节点的hash值等于hash 且第一个节点的key等于key
        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);
        }
    }
    // 找不到返回null
    return null;
}

猜你喜欢

转载自blog.csdn.net/qq_37248504/article/details/110007064
今日推荐