关闭

equals 和 ==, equals 和 hashcode

标签: equalshashcodejava
133人阅读 评论(0) 收藏 举报
分类:

equals 和 ==, equals 和 hashcode

回顾下 Java 的一些基础知识

测试类

public class Person {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

1. equals 和 ==

  1. equals 默认就是 == ,比较引用内存地址
  2. String、Integer 等类重写了 equals 方法, 比较值

Object.equals 源码

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

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;
}

测试

 @Test
public void StringEquals() {
    String a = "123";
    String b = new String("123");
    assertEquals(a, b);
    assertTrue(a.equals(b));
    assertFalse(a == b); // 涉及到常量池
}

常量池就不细抠了,网上太多了。

重写 equlas 方法

那么对于引用类型,默认 equals 也是 ==。但是对于业务来说,通常内部值相等,就算相同了,可以重写 equals 方法,使之可以进行比较。

重写 Person.equals

@Override
public boolean equals(Object o) {
    // 相同的引用地址
    if (this == o) return true;

    //  不是本类的实例
    if (o == null || getClass() != o.getClass()) return false;

    Person person = (Person) o;
    // 比较具体值
    return age == person.age && name.equals(person.name);

}

测试

// 对于对象,重写 equals 使之可以进行值的比较
@Test
public void ObjectEquals() {
    Person a = new Person("hehe", 10);
    Person b = new Person("hehe", 10);
    // 默认比较引用地址 false
//        assertNotEquals(a, b);
    assertEquals(a, b);
}

2. equals 和 hashcode

重写 equals 为什么要重写 hashcode 方法?这是初学 Java 时经常看到的问题。

来看下 hashcode 方法的注释,之前并没有自己看过,都是各种文章撸过去的

 /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

简单的说就是主要用于 HashMap,当然也涉及到 LinkedHashMap、HashSet等

约定一下
1. 程序执行过程中,对同一对象多次调用 hashcode 应当返回一直,前提是将对象进行 equals 比较时所用的信息没有被修改。
2. 如果俩对象 equals, 则 hashCode 也应该相等
3. 如果俩对象不 equals,则不要求 hashcode 相等。但程序员们应当知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。

所以其实刚才的问题就不是问题了,哪那么多道道,要求怎么来就怎么来呗,重写 equals 的时候顺带重写了 hashcode 方法,用以保证集合中元素唯一。

集合先判断 hashcode 是否相同,不同则为不同对象。但对象的 hashcode 默认是不同的(返回的实际上是该对象在jvm的堆上的内存地址,而不同对象的内存地址肯定不同),所以重写 equals 判断俩对象相同后集合却不承认,所以要重写 hashcode

如果 hashcode 相同(目测通常是人为因素),再判断 equals,不同则为不同对象。反之为相同对象。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    最新评论