【JAVA基础】equal和hashcode的区别

简介: 【JAVA基础】equal和hashcode的区别

面试时被问到了equal和hashcode的区别,在这里总结一下:

一、equals()


equals是根类Obeject中的方法。源代码如下:

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



可见默认的equals方法,直接调用==,比较对象地址。不同的子类,可以重写此方法,进行两个对象的equals的判断。

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



从上面的代码中可以看到,

(1)String类中的equals首先比较地址,如果是同一个对象的引用,可知对象相等,返回true

(2)如果不是同一个对象,equals方法挨个比较两个字符串对象内的字符,只有完全相等才返回true,否则返回false


二、hashcode()

hashCode是根类Obeject中的方法。

  默认情况下,Object中的hashCode()返回对象的32jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32JVM内存地址。

  String类源码中重写的hashCode方法如下:

  public int hashCode() {
      int h = hash;    //Default to 0 ### String类中的私有变量,
      if (h == 0 && value.length > 0) {    //private final char value[]; ### Sting类中保存的字符串内容的的数组
          char val[] = value;
         for (int i = 0; i < value.length; i++) {
              h = 31 * h + val[i];
          }
         hash = h;
     }
     return h;
 }



String源码中使用private final char value[];保存字符串内容,因此String是不可变的。


   看下面的例子,没有重写hashCode方法的类,直接返回32位对象在JVM中的地址;Long类重写了hashCode方法,返回计算出的hashCode数值:

public class ComHashcode{
      public static void main(String[] args) throws Exception {
          ComHashcode a = new ComHashcode();
          ComHashcode b = new ComHashcode();
          System.out.println(a.hashCode());    
          System.out.println(b.hashCode());    
          Long num1 = new Long(8);
          Long num2 = new Long(8);
         System.out.println(num1.hashCode());    
         System.out.println(num2.hashCode());   
     }
 }

三、hashCode和equals的关系:


如果两个对象相等(equal),它们的hashcode一定相同;


  如果两个对象有相同的hashcode,它们不一定相等(equal);


  之所以这样设计是为了在Map中更快的查找到对象(相对于线性搜索);


  一般Map都设计成数组+链表的结构,使用hashcode去查找对象需要两个步骤,首先使用hashcode定位数组下标索引,然后遍历该数组元素对应的链表,找到equals的元素;


  Object默认的hashcode实现对于不同的对象会返回不同的值,值的散列就像在车库储存货物,不同的货物能被存放到不同的车库。比较有效查找货物办法是将不同的货物存到不同的车库中,而不是同一个车库;


因此,通过hashCode可以很快的查到小内存块,而且通过hashCode比较比equal方法快,当get时先比较hashCode,如果hashCode不同,直接返回false。


相关文章
|
22天前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
55 9
|
28天前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
60 12
|
2月前
|
Java
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
|
3月前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
107 14
|
2月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
36 1
|
3月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
104 8
|
3月前
|
Java
Java代码解释++i和i++的五个主要区别
本文介绍了前缀递增(++i)和后缀递增(i++)的区别。两者在独立语句中无差异,但在赋值表达式中,i++ 返回原值,++i 返回新值;在复杂表达式中计算顺序不同;在循环中虽结果相同但使用方式有别。最后通过 `Counter` 类模拟了两者的内部实现原理。
Java代码解释++i和i++的五个主要区别
|
4月前
|
Java
通过Java代码解释成员变量(实例变量)和局部变量的区别
本文通过一个Java示例,详细解释了成员变量(实例变量)和局部变量的区别。成员变量属于类的一部分,每个对象有独立的副本;局部变量则在方法或代码块内部声明,作用范围仅限于此。示例代码展示了如何在类中声明和使用这两种变量。
|
5月前
|
Java
java基础(4)public class 和class的区别及注意事项
本文讲解了Java中`public class`与`class`的区别和注意事项。一个Java源文件中只能有一个`public class`,并且`public class`的类名必须与文件名相同。此外,可以有多个非`public`类。每个类都可以包含一个`main`方法,作为程序的入口点。文章还强调了编译Java文件生成`.class`文件的过程,以及如何使用`java`命令运行编译后的类。
104 3
java基础(4)public class 和class的区别及注意事项
|
4月前
|
Java
Java基础之 JDK8 HashMap 源码分析(中间写出与JDK7的区别)
这篇文章详细分析了Java中HashMap的源码,包括JDK8与JDK7的区别、构造函数、put和get方法的实现,以及位运算法的应用,并讨论了JDK8中的优化,如链表转红黑树的阈值和扩容机制。
59 1