Java基础之hashCode()的作用,以及==、equals()和hashCode()区别
2016-12-27 15:10
609 查看
1 ==、equals()和hashCode()
1.1 ==
==操作符用来比较两个基本类型变量时(byte、short、char、int、long、float、double、boolean),比较的是值;用来比较引用类型变量时(非基本类型),比较的是引用的地址。1.2 equals()
equals方法是基类Object的方法,用于比较两个对象的内容是否相同,Object类中equals方法的默认实现使用的==操作符比较。所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals()方法,这个方法的初始行为是比较对象的内存地址,实际开发过程中重写了equals方法,重新定义比较规则,如:String、Integer、Date在这些类重写了equals()方法,而不再是比较类在堆内存中的存放地址了。
1.3 hashCode()
hashCode()返回的就是对象的存储地址,事实上这种看法是不全面的,确实有些JVM在实现时是直接返回对象的存储地址,但是大多时候并不是这样,只能说可能存储地址有一定关联。hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable(注意:集合中不允许重复的元素存在)。当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?
也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了.
说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。下面这段代码是java.util.HashMap的中put方法的具体实现:
// 将“key-value”添加到HashMap中 public V put(K key, V value) { // 若“key为null”,则将该键值对添加到table[0]中。 if (key == null) return putForNullKey(value); // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出! if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } //若“该key”对应的键值对不存在,则将“key-value”添加到table中 modCount++; //将key-value添加到table[i]处 addEntry(hash, key, value, i); return null; }
put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。
从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。
2 ==和equals()比较
2.1 基本数据类型的值比较使用==
基本数据类型,也称原始数据类型。它们之间的比较,使用==,比较的是他们的值。 即内容相同,我们就认为是相等的。public class Test { public static void main(String[] args) { int i=5; int j=5; if(i==j) { System.out.println("i和j相等!"); } else { System.out.println("不相等!"); } } }
i和j相等!
2.2 复合数据类型的比较使用equals()
当(String,Integer,Date) 用==进行比较的时候,比较的是他们在内存中的存放地址,所以除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。由以下代码解析:String str1 = new String("hello"); String str2 = "hello"; String str3 = "h"; System.out.println("str1==str2: " + (str1==str2)); //false System.out.println("str1.equals(str2): " + str1.equals(str2)); //true System.out.println("str1.hashCode(): " + str1.hashCode()); System.out.println("str2.hashCode(): " + str2.hashCode()); System.out.println("str3.hashCode(): " + str3.hashCode());
输出结果:
2.3 对象类型比较使用equals()
(1)==号:对比对象实例的内存地址来判断是否是同一对象实例,也可以说是判断对象实例是否物理相等。(2)equals():当对象实例没有重写Object的equals方法时,equals方法判断的是对象实例的内存地址是否是同一对象实例。
//Object类的源码如下 public boolean equals(Object obj) { return (this == obj); }
(3)例子
public class Test { public static void main(String[] args) { Student s = new Student("BlueSky"); Student s1 = new Student("BlueSky"); if (s == s1) { System.out.println("s和是s1相等!"); } else { System.out.println("s和是s1不相等!"); } if (s.equals(s1)) { System.out.println("s和是s1相等!"); } else { System.out.println("s和是s1不相等!"); } } }
s和是s1不相等! s和是s1不相等!
3 HashCode()与equals()方法的关系
可以直接根据hashcode值判断两个对象是否相等吗?肯定是不可以的,因为不同的对象可能会生成相同的hashcode值。虽然不能根据hashcode值判断两个对象是否相等,但是可以直接根据hashcode值判断两个对象不等,如果两个对象的hashcode值不等,则必定是两个不同的对象。如果要判断两个对象是否真正相等,必须通过equals方法。关系如下:
如果equals方法得到的结果为true,则两个对象的hashcode值必定相等;
如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;
如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;
如果两个对象的hashcode值相等,则equals方法得到的结果未知。
4 详细关注链接
数据结构与算法之Collection和Map综述-HashMapHashMap源码剖析.md
相关文章推荐
- Java基础 hashCode() 和equals() 区别和作用
- Java基础 equals()、hashCode()和 == 区别
- java(15):基础:“==”、equals()和hashCode()的区别
- Java中==与equals()以及hashCode()的区别
- java基础之 “==”和“ equals”以及instanceof的区别
- Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例
- java基础 equals与==区别,String的hashcode
- [Java基础] HashCode、equals、==的区别
- java基础复习(二) ==和equals和hashCode的区别
- java基础-hashCode()和equals()的本质区别和联系
- 【转】Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例
- Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)
- java基础 5、作用域public,private,protected,以及不写时的区别
- java基础之 “==”和“ equals”以及instanceof的区别
- java关于equals与==号的区别以及与hashCode的关系
- 面试题之java基础:equals()和hashCode()区别?
- java基础之 “==”和“ equals”以及instanceof的区别
- Java 中equal() 方法与==的区别以及 equals()与 hashCode()方法重写
- java基础面试知识点---------java中==和equals和hashCode的区别
- [厉害了,我的JAVA基础](十一)hashCode与equals的区别与联系