博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java--map容器的hashcode和equals
阅读量:5227 次
发布时间:2019-06-14

本文共 2462 字,大约阅读时间需要 8 分钟。

先看一个例子

首先定义一个user类。

package com.text.tool;public class User {	int id;	User(int id) {		this.id = id;	}	public String toString() {		return "key="+id;	}}

其次写一个测试类,创建一个HashMap,在map中User对象作为KEY。

package com.text.tool;import java.util.HashMap;import java.util.Map;public class TestMap {	public static void main(String[] args) {		Map map = new HashMap();		map.put(new User(1), 1);		map.put(new User(2), 1);		map.put(new User(3), 1);				System.out.println(map.keySet());		System.out.println(map.get(new User(1))	}}

输出结果,让人疑惑的是为什么MAP数组中匹配不到new User(1)。

[key=1, key=2, key=3]null

我们可以简单看下HashMap源码,在源码中获取到key对应value做了一个判断,e.hash == hash && eq(k, e.key)也就是对key的hashcode进行比对,以及进行equals判断。

我们传入的对象User默认继承Object,所以equals及hashCode默认是Object的方法,而此时这里的equals比较的是两个对象的内存中的地址并非value,所以第二个new User(1)就无法再MAP数组中取到value了。

public Object get(Object key) {        Object k = maskNull(key);        int hash = hash(k);        int i = indexFor(hash, table.length);        Entry e = table[i];         while (true) {            if (e == null)                return e;            if (e.hash == hash && eq(k, e.key))                 return e.value;            e = e.next;        }    }
public boolean equals(Object obj) {	return (this == obj);    }
public native int hashCode();

在User类中重写equals及hashcode方法,在启用main方法就不会有问题了。

package com.text.tool;public class User {	int id;	User(int id) {		this.id = id;	}	public String toString() {		return "key="+id;	}		public int hashCode() {		return id;	}	public boolean equals(Object o) {		return o instanceof User && (id == ((User) o).id);	}}

执行MAIN方法输出结果:

[key=2, key=1, key=3]1

截取think in java一段描述:

 

 

equals()相等的两个对象,hashcode()一定相等; 
equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。(我的理解是由于哈希码在生成的时候产生冲突造成的)。 
反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解释下第3点的使用范围,我的理解是在object、String等类中都能使用。在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了;在String类中,equals()返回的是两个对象内容的比较,当两个对象内容相等时, 
Hashcode()方法根据String类的重写代码的分析,也可知道hashcode()返回结果也会相等。以此类推,可以知道Integer、Double等封装类中经过重写的equals()和hashcode()方法也同样适合于这个原则。当然没有经过重写的类,在继承了object类的equals()和hashcode()方法后,也会遵守这个原则。

附下哈希表结构:

 

 

在一个数组中存储对象时,通过 hashCode 得到的哈希值来计算数组的索引位置(通常是求余运算),然后根据这个索引位置进行存取。多个对象计算出来的索引位置相同(叫hash冲突)时,用链表保存。冲突怎么保证取到的就是自己呢?那么就要用到 Object.equals() 方法。

所以要把对象存储在像 hash table类似的数据结构(比如:HashSet)中,hashCode 与 equals 要成对实现。

 

部分内容来源:

 

 

 

转载于:https://www.cnblogs.com/dyllove98/p/3233662.html

你可能感兴趣的文章
数据库事务隔离级别与锁
查看>>
Effetive Java 22 Favor static member classes over nonstatic
查看>>
SVN 使用
查看>>
9.4Html
查看>>
14.inline与namespace使用
查看>>
SVN的使用
查看>>
Java空字符串与null的区别和判断字符串是否为空的方法
查看>>
第二阶段冲刺第八天
查看>>
数学小记
查看>>
【BZOJ4197】【Noi2015】寿司晚宴
查看>>
如何解决:登录桌面时自动运行的EXE提示“该程序没有与之关联来执行操作”,之后出现蓝屏代码0xc000021a...
查看>>
vue history 模式打包部署在域名的二级目录的配置指南
查看>>
读《深入理解Elasticsearch》点滴-改善查询相关性
查看>>
RabbitMQ 使用(一)
查看>>
强大的PHP压缩与解压缩zip类
查看>>
[DELPHI]$2501錯誤處理
查看>>
c#小数取整
查看>>
Margin和padding失效
查看>>
cdcq的独立博客上线辣!-> http://cdcq.coding.me/blog/
查看>>
MySQL性能调优与架构设计——第13章 可扩展性设计之 MySQL Replication
查看>>