腾讯2分彩网站地址_为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

  • 时间:
  • 浏览:1

     我在面试 Java初级开发的刚刚,老要会问:你有什么什么都没办法 重写过hashcode最好的办法?不少候选人直接说没写过。我就想,或许真的没写过,于是就再通过一个多多 哪几种的间题确认:你在用HashMap的刚刚,键(Key)每项,有什么什么都没办法 放过自定义对象?而你你这名 刚刚,候选人说放过,于是一个多多 哪几种的间题的回答就自相矛盾了。

    最近问下来,你你这名 哪几种的间题普遍回答不大好,于是在本文里,就干脆从hash表讲起,讲述HashMap的存数据规则,由此我们歌词 歌词 都就自然清楚上述哪几种的间题的答案了。

1 通过Hash算法来了解HashMap对象的高效性

    我们歌词 歌词 都先复习数据特性里的一个多多 知识点:在一个多多 长度为n(假设是500)的线性表(假设是ArrayList)里,存放着无序的数字;不可能 我们歌词 歌词 全部都是找一个多多 指定的数字,就不得不通过从头到尾依次遍历来查找,另一个多多 的平均查找次数是n除以2(这里是500)。

我们歌词 歌词 都再来观察Hash表(这里的Hash表纯粹是数据特性上的概念,和Java无关)。它的平均查找次数接近于1,代价相当小,关键是在Hash表里,存装进去其中的数据和它的存储位置是用Hash函数关联的。

    我们歌词 歌词 都假设一个多多 Hash函数是x*x%5。当然实际情况报告里无需可能 用什么什么都没办法 简单的Hash函数,我们歌词 歌词 都这里纯粹为了说明方便,而Hash表是一个多多 长度是11的线性表。不可能 我们歌词 歌词 全部都是把6装进去其中,什么什么都没办法 我们歌词 歌词 都首先会对6用Hash函数计算一下,结果是1,就说 我我们歌词 歌词 都就把6装进去到索引号是1你你这名 位置。同样不可能 我们歌词 歌词 全部都是放数字7,经过Hash函数计算,7的结果是4,什么什么都没办法 它将被装进去索引是4的你你这名 位置。你你这名 效果如下图所示。

    另一个多多 做的好处非常明显。比如我们歌词 歌词 全部都是从中找6你你这名 元素,我们歌词 歌词 前要先通过Hash函数计算6的索引位置,只要直接从1号索引里找到它了。

不过我们歌词 歌词 都会遇到“Hash值冲突”你你这名 哪几种的间题。比如经过Hash函数计算后,7和8会有相同的Hash值,对此Java的HashMap对象采用的是”链地址法“的出理 方案。效果如下图所示。

 

    具体的做法是,为所有Hash值是i的对象建立一个多多 同义词链表。假设我们歌词 歌词 全部都是装进去8的刚刚,发现4号位置不可能 被占,什么什么都没办法 就会新建一个多多 链表结点装进去8。同样,不可能 我们歌词 歌词 全部都是找8,什么什么都没办法 发现4号索引里全部都是8,那会沿着链表依次查找。

    其实我们歌词 歌词 都还是无法彻底出理 Hash值冲突的哪几种的间题,只要Hash函数设计合理,仍能保证同义词链表的长度被控制在一个多多 合理的范围里。这里讲的理论知识不须无的放矢,我们歌词 歌词 都能在后文里清晰地了解到重写hashCode最好的办法的重要性。

2 为哪几种要重写equals和hashCode最好的办法

    我们歌词 歌词 都都用HashMap存入自定义的类时,不可能 不重写你你这名 自定义类的equals和hashCode最好的办法,得到的结果会和我们歌词 歌词 都预期的不一样。我们歌词 歌词 都来看WithoutHashCode.java你你这名 例子。

在其中的第2到第18行,我们歌词 歌词 都定义了一个多多 Key类;在其中的第3行定义了唯一的一个多多 属性id。当前我们歌词 歌词 都先注释掉第9行的equals最好的办法和第16行的hashCode最好的办法。    

1	import java.util.HashMap;
2	class Key {
3		private Integer id;
4		public Integer getId() 
5	{return id; }
6		public Key(Integer id) 
7	{this.id = id;	}
8	//故意先注释掉equals和hashCode最好的办法
9	//	public boolean equals(Object o) {
10	//		if (o == null || !(o instanceof Key)) 
11	//		{ return false;	} 
12	//		else 
13	//		{ return this.getId().equals(((Key) o).getId());}
14	//	}
15		
16	//	public int hashCode() 
17	//	{ return id.hashCode();	}
18	}
19	
20	public class WithoutHashCode {
21		public static void main(String[] args) {
22			Key k1 = new Key(1);
23			Key k2 = new Key(1);
24			HashMap<Key,String> hm = new HashMap<Key,String>(); 
25			hm.put(k1, "Key with id is 1");		
26			System.out.println(hm.get(k2));		
27		}
28	}

    在main函数里的第22和23行,我们歌词 歌词 都定义了一个多多 Key对象,它们的id全部都是1,就好比它们是两把相同的都能打开同一扇门的钥匙。

    在第24行里,我们歌词 歌词 都通过泛型创建了一个多多 HashMap对象。它的键每项前要存放Key类型的对象,值每项前要存储String类型的对象。

    在第25行里,我们歌词 歌词 都通过put最好的办法把k1和一串字符装进去到hm里; 而在第26行,我们歌词 歌词 都想用k2去从HashMap里得到值;这就好比我们歌词 歌词 都想用k1这把钥匙来锁门,用k2来开门。这是符合逻辑的,但从当前结果看,26行的返回结果全部都是我们歌词 歌词 都想象中的那个字符串,就说 我null。

    愿因有一个多多 —什么什么都没办法 重写。第一是什么什么都没办法 重写hashCode最好的办法,第二是什么什么都没办法 重写equals最好的办法。

   我们歌词 歌词 都都往HashMap里放k1时,首先会调用Key你你这名 类的hashCode最好的办法计算它的hash值,但是把k1装进去hash值所指引的内存位置。

    关键是我们歌词 歌词 都什么什么都没办法 在Key里定义hashCode最好的办法。这里调用的仍是Object类的hashCode最好的办法(所有的类全部都是Object的子类),而Object类的hashCode最好的办法返回的hash值其实是k1对象的内存地址(假设是50)。

    

    不可能 我们歌词 歌词 都但是是调用hm.get(k1),什么什么都没办法 我们歌词 歌词 都会再次调用hashCode最好的办法(还是返回k1的地址50),但是根据得到的hash值,能调慢地找到k1。

    但我们歌词 歌词 都这里的代码是hm.get(k2),我们歌词 歌词 都都调用Object类的hashCode最好的办法(不可能 Key里没定义)计算k2的hash值时,其实得到的是k2的内存地址(假设是50)。不可能 k1和k2是一个多多 不同的对象,就说 我它们的内存地址一定无需相同,也就说 我说它们的hash值一定不同,这就说 我我们歌词 歌词 都无法用k2的hash值去拿k1的愿因。

    我们歌词 歌词 都都把第16和17行的hashCode最好的办法的注释加进后,会发现它是返回id属性的hashCode值,这里k1和k2的id全部都是1,就说 我它们的hash值是相等的。

    我们歌词 歌词 都再来更正一下存k1和取k2的动作。存k1时,是根据它id的hash值,假设这里是50,把k1对象装进去到对应的位置。而取k2时,是先计算它的hash值(不可能 k2的id也是1,你你这名 值也是50),但是到你你这名 位置去找。

    但结果会出乎我们歌词 歌词 都意料:明明50号位置不可能 有k1,但第26行的输出结果依然是null。其愿因就说 我什么什么都没办法 重写Key对象的equals最好的办法。

    HashMap是用链地址法来出理 冲突,也就说 我说,在50号位置上,有不可能 处在着多个用链表形式存储的对象。它们通过hashCode最好的办法返回的hash值全部都是50。

     我们歌词 歌词 都都通过k2的hashCode到50号位置查找时,其实会得到k1。但k1有不可能 仅仅是和k2具有相同的hash值,但不须和k2相等(k1和k2两把钥匙不须能开同一扇门),你你这名 刚刚,就前要调用Key对象的equals最好的办法来判断两者是与否相等了。

    不可能 我们歌词 歌词 全部都是Key对象里什么什么都没办法 定义equals最好的办法,系统就不得不调用Object类的equals最好的办法。不可能 Object的固有最好的办法是根据一个多多 对象的内存地址来判断,就说 我k1和k2一定无需相等,这就说 我为哪几种依然在26行通过hm.get(k2)依然得到null的愿因。

    为了出理 你你这名 哪几种的间题,我们歌词 歌词 都前要打开第9到14行equals最好的办法的注释。在你你这名 最好的办法里,只要一个多多 对象全部都是Key类型,只要它们的id相等,它们就相等。

3 对面试哪几种的间题的说明

    不可能 在项目里老要会用到HashMap,就说 我我在面试的刚刚总要问你你这名 哪几种的间题∶你有什么什么都没办法 重写过hashCode最好的办法?你在使用HashMap时有什么什么都没办法 重写hashCode和equals最好的办法?你是要怎样写的?

    根据问下来的结果,我发现初级守护程序运行运行员对你你这名 知识点普遍没掌握好。重申一下,不可能 我们歌词 歌词 全部都是在HashMap的“键”每项存放自定义的对象,一定要在你你这名 对象里用当时人的equals和hashCode最好的办法来覆盖Object里的同名最好的办法。 

     本文是从Java核心技术及面试指南这本书中相关内容改编而来。