hashCode与equal,==与equal的区别

了解hashcode


public class HashcodeTest {

	public static void main(String[] args) {
		Integer i1=new Integer(100);
		int j = 100;
		System.out.println(i1 == j); //true
		System.out.println(i1.hashCode());//100

		System.out.println(System.identityHashCode(i1));//打印地址
		System.out.println(System.identityHashCode(j));
		
		Integer i2=new Integer(128);
		System.out.println(i2.hashCode());//128
		
		Integer i3=128;
		System.out.println(i3.hashCode());//128
		//integer自动拆装箱范围为-128-127,在范围内直接到常量池中取
		System.out.println(i2==i3);//false
		System.out.println(i2.equals(i3));//true
		
		System.out.println(System.identityHashCode(i2));//打印地址
		System.out.println(System.identityHashCode(i3));
	}

}

结果:
在这里插入图片描述

integer与int区别

equals和HashCode的关系

  • 1.equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的。
  • 2.hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。

所有对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!

为什么重写equals有必要重写hashcode?

打个比方,一个名叫张三的人去住酒店,在前台登记完名字就去了99层100号房间,此时警察来前台找叫张三的这个人住在哪间房,经过查询,该酒店住宿的有50个叫张三的,需要遍历查询,查询起来很不方便。

那么就换另外一种登记方式,前台登记时登记身份证号,警察来前台找身份证号时发现身份证号也存在重复,经过哈希算法进行计算后相同的hashcode值被分到了一个房间然后产生链表,链表查询效率非常慢,然后警察找的时候也会遇到问题。

那么只能换第三种登记方式了,前台登记时同时登记身份证号和名字,这样警察来找的时候同时按照两个条件去查,这样就能直接锁定要找的人在哪个房间。


在程序中:登记的前台好比哈希算法,名字是对比好比 equals 方法,身份证号的对比好比 hashcode 方法只有equals 和 hashcode 都满足的时候才能确保是同一个对象。

当我们重写一个类的 equals 方法时就应当连同重写 hashcode 方法,并且两个方法应满足:

1:一致性,即:当两个对象 equals 比较为 true,那么 hashcode 值应当相等,反之亦然,因为当两个对象hashcode 值相等,但是 equals 比较为 false,那么在 HashMap 中会产生链表,影响查询性能。

2:成对重写,即重写 equals 就应当重写 hashcode。实际上这只是一条规范,如果不这样做程序也可以执行,只不过会隐藏bug。一般一个类的对象如果会存储在HashTable,HashSet,HashMap等散列存储结构中,那么重写equals后最好也重写hashCode,否则会导致存储数据的不唯一性(存储了两个equals相等的数据),因为map结构中的key可以是对象,两个对象的值相同但地址不同,则取出value会出现问题。而如果确定不会存储在这些散列结构中,则可以不重写hashCode。

package com.zejian.test;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
	public static void main(String[] args) {
		Map<String,Value> map1 = new HashMap<String,Value>();
		String s1 = new String("key");
		String s2 = new String("key");	
		Value value = new Value(2);
		map1.put(s1, value);
		System.out.println("s1.equals(s2):"+s1.equals(s2));
		System.out.println("map1.get(s1):"+map1.get(s1));
		System.out.println("map1.get(s2):"+map1.get(s2));
		
		
		Map<Key,Value> map2 = new HashMap<Key,Value>();
		Key k1 = new Key("A");
		Key k2 = new Key("A");
		map2.put(k1, value);
		System.out.println("k1.equals(k2):"+k1.equals(k2));
		System.out.println("map2.get(k1):"+map2.get(k1));
		System.out.println("map2.get(k2):"+map2.get(k2));
	}
	
	/**
	 * 键
	 * @author zejian
	 *
	 */
	static class Key{
		private String k;
		public Key(String key){
			this.k=key;
		}
		
		@Override
		public boolean equals(Object obj) {
			if(obj instanceof Key){
				Key key=(Key)obj;
				return k.equals(key.k);
			}
			return false;
		}
	}
	
	/**
	 * 值
	 * @author zejian
	 *
	 */
	static class Value{
		private int v;
		
		public Value(int v){
			this.v=v;
		}
		
		@Override
		public String toString() {
			return "类Value的值-->"+v;
		}
	}
}

结果:

s1.equals(s2):true
map1.get(s1):类Value的值-->2
map1.get(s2):类Value的值-->2
k1.equals(k2):true
map2.get(k1):类Value的值-->2
map2.get(k2):null

equals和==的关系

  1. equals和==的区别
    ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
  2. equals 比较的话 先比较地址,如果相等,直接返回true 然后看比较的对象是不是类型相同,如果不是直接返回false
    如果是的话,则依次比较里面的内容,如果全部相等,则返回true

(这里需要注意string比较,string为引用类型,不是基本类型,用equal和==比较可能不一样)
基本类型与引用类型区别

©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页