极速快3app二维码_为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

  • 时间:
  • 浏览:4
  • 来源:上海网_专注上海新闻_上海的主流媒体

     我在面试 Java初级开发的后来,老要 会问:你有没办法 重写过hashcode方式 ?不少候选人直接说没写过。让他想,或许真的没写过,于是就再通过1个多 大现象确认:你在用HashMap的后来,键(Key)每种,有没办法 放过自定义对象?而这些 后来,候选人说放过,于是1个多 大现象的回答就自相矛盾了。

    最近问下来,这些 大现象普遍回答不大好,于是在本文里,就干脆从hash表讲起,讲述HashMap的存数据规则,由此当我们当我们儿就自然清楚上述大现象的答案了。

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

    当我们当我们儿先复习数据底部形态里的1个多 知识点:在1个多 长度为n(假设是111500)的线性表(假设是ArrayList)里,存放着无序的数字;不可能 当我们当我们儿要找1个多 指定的数字,就不得不通过从头到尾依次遍历来查找,那我的平均查找次数是n除以2(这里是11500)。

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

    当我们当我们儿假设1个多 Hash函数是x*x%5。当然实际情况里后该可能 用没办法 简单的Hash函数,当我们当我们儿这里纯粹为了说明方便,而Hash表是1个多 长度是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的对象建立1个多 同义词链表。假设当我们当我们儿在倒进8的后来,发现4号位置不可能 被占,没办法 就会新建1个多 链表结点倒进8。同样,不可能 当我们当我们儿要找8,没办法 发现4号索引里算不算 8,那会沿着链表依次查找。

    其实当我们当我们儿还是无法彻底正确处理Hash值冲突的大现象,而且Hash函数设计合理,仍能保证同义词链表的长度被控制在1个多 合理的范围里。这里讲的理论知识暂且无的放矢,当我们当我们儿能在后文里清晰地了解到重写hashCode方式 的重要性。

2 为哪几种要重写equals和hashCode方式

    当当我们当我们儿用HashMap存入自定义的类时,不可能 不重写这些 自定义类的equals和hashCode方式 ,得到的结果会和当我们当我们儿预期的不一样。当我们当我们儿来看WithoutHashCode.java这些 例子。

在其中的第2到第18行,当我们当我们儿定义了1个多 Key类;在其中的第3行定义了唯一的1个多 属性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行,当我们当我们儿定义了1个多 Key对象,它们的id算不算 1,就好比它们是两把相同的都能打开同一扇门的钥匙。

    在第24行里,当我们当我们儿通过泛型创建了1个多 HashMap对象。它的键每种后该 存放Key类型的对象,值每种后该 存储String类型的对象。

    在第25行里,当我们当我们儿通过put方式 把k1和一串字符倒进到hm里; 而在第26行,当我们当我们儿想用k2去从HashMap里得到值;这就好比当我们当我们儿想用k1这把钥匙来锁门,用k2来开门。这是符合逻辑的,但从当前结果看,26行的返回结果算不算 当我们当我们儿想象中的那个字符串,什么都有有什么都有有null。

    原困 1个多多 —没办法 重写。第一是没办法 重写hashCode方式 ,第二是没办法 重写equals方式 。

   当当我们当我们儿往HashMap里放k1时,首先会调用Key这些 类的hashCode方式 计算它的hash值,后来把k1倒进hash值所指引的内存位置。

    关键是当我们当我们儿没办法 在Key里定义hashCode方式 。这里调用的仍是Object类的hashCode方式 (所有的类算不算 Object的子类),而Object类的hashCode方式 返回的hash值其实是k1对象的内存地址(假设是11150)。

    

    不可能 当我们当我们儿后来是调用hm.get(k1),没办法 当我们当我们儿会再次调用hashCode方式 (还是返回k1的地址11150),后来根据得到的hash值,能很快地找到k1。

    但当我们当我们儿这里的代码是hm.get(k2),当当我们当我们儿调用Object类的hashCode方式 (不可能 Key里没定义)计算k2的hash值时,其实得到的是k2的内存地址(假设是1150)。不可能 k1和k2是1个多 不同的对象,什么都有有什么都有有它们的内存地址一定后该相同,也什么都有有什么都有有说它们的hash值一定不同,这什么都有有什么都有有当我们当我们儿无法用k2的hash值去拿k1的原困 。

    当当我们当我们儿把第16和17行的hashCode方式 的注释再加后,会发现它是返回id属性的hashCode值,这里k1和k2的id算不算 1,什么都有有什么都有有它们的hash值是相等的。

    当我们当我们儿再来更正一下存k1和取k2的动作。存k1时,是根据它id的hash值,假设这里是1150,把k1对象倒进到对应的位置。而取k2时,是先计算它的hash值(不可能 k2的id也是1,这些 值也是1150),后来到这些 位置去找。

    但结果会出乎当我们当我们儿意料:明明1150号位置不可能 有k1,但第26行的输出结果依然是null。其原困 什么都有有什么都有有没办法 重写Key对象的equals方式 。

    HashMap是用链地址法来正确处理冲突,也什么都有有什么都有有说,在1150号位置上,有不可能 存在着多个用链表形式存储的对象。它们通过hashCode方式 返回的hash值算不算 1150。

     当当我们当我们儿通过k2的hashCode到1150号位置查找时,其实会得到k1。但k1有不可能 仅仅是和k2具有相同的hash值,但暂且和k2相等(k1和k2两把钥匙暂且能开同一扇门),这些 后来,就时要调用Key对象的equals方式 来判断两者算不算 相等了。

    不可能 当我们当我们儿在Key对象里没办法 定义equals方式 ,系统就不得不调用Object类的equals方式 。不可能 Object的固有方式 是根据1个多 对象的内存地址来判断,什么都有有什么都有有k1和k2一定后该相等,这什么都有有什么都有有为哪几种依然在26行通过hm.get(k2)依然得到null的原困 。

    为了正确处理这些 大现象,当我们当我们儿时要打开第9到14行equals方式 的注释。在这些 方式 里,而且1个多 对象算不算 Key类型,而且它们的id相等,它们就相等。

3 对面试大现象的说明

    不可能 在项目里老要 会用到HashMap,什么都有有什么都有有我在面试的后来算不算 问这些 大现象∶你有没办法 重写过hashCode方式 ?你在使用HashMap时有没办法 重写hashCode和equals方式 ?你是为啥写的?

    根据问下来的结果,我发现初级多多线程 员对这些 知识点普遍没掌握好。重申一下,不可能 当我们当我们儿要在HashMap的“键”每种存放自定义的对象,一定要在这些 对象里用被委托人的equals和hashCode方式 来覆盖Object里的同名方式 。 

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

猜你喜欢

大发10分彩信誉网_2019Q1中国社区拼团报告:线上线下巨头涌入

2018年尤其是下5天始于英文英语 社区大发10分彩信誉网拼团迎来风口,用户规模高达上亿级,巨头及资本裹挟而来,社区拼团赛道十足火热。 第三方数据挖掘及市场研究机构比达(Bi

2020-01-25

3分时时彩计划_善缘叙沉香茶品茶者的新宠,掀起茶行业新思路

 近年来随着生活水平3分时时彩计划的提高和消费者理念的转变,大多数许多人都把养生重视了起来3分时时彩计划。从饮食到健身,形体瑜伽和饮茶,饮水有的是较高的要求。都注重绿色环保,把

2020-01-25

10分pk10靠谱吗_ “黄金四分钟”,这些急救知识要牢记

癫痫10分pk10靠谱吗患者发作时的确将会咬到舌头,但不用会致命,最多像吃饭咬伤一样,絮状出血,反而往嘴里塞勺子等硬物将会伤害牙齿,塞衣物、毛巾等柔软物品将会影响患者呼吸,压舌

2020-01-25

极速1分快3网址_成都链家四场活动齐开 万人同聚闹元宵

2017年2月11日(农历正月十五)下午2时许,主题为“左邻右里•欢闹元宵”的成都链家大型元宵活动在成都蜀都花园小区、郫都区蜀都万达广场、成都南城都汇小区、新都区新城市广场四大

2020-01-25

好运十分快三骗局_新疆鸟友捉到世界最小跳鼠 体重相当一元硬币

 最小跳鼠都市消费晨报讯(记者赵梅报道)脸长的像小猪,外形跟老鼠差太满,身体一缩比矿泉水玻璃瓶略大许多。近日,和田鸟友陈文杰在民丰县萨勒吾则克乡吾塘村发现了这奇特的小跳鼠。新疆

2020-01-25