【Java杂记】Equals 和 hashCode
equals 和 hashCode含义
equal:判断两个对象是否相等,如果相同,返回true 否则返回false
hashcode: 返回一个int数 Object 默认(内部地址转化为一个数字)
两者关系
如果equals(obj)返回true, 那么 hashCode一定返回一样的值
如果equals(obj)返回false, 那么 hashCode 不一定返回一样的值
如果hashCode 返回相同的数,那么 equals 不一定返回true
如果hashCode返回不一样的数,那么equals 一定返回false
集合中使用
放入流程
放入散列时候,先比较hashCode, 然后判断equals
HashSet 放入元素
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap 放入元素
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
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;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}
测试一: 覆盖 equals 不覆盖 hashCode
public class HashCodeTest {
public static void main(String[] args) {
Collection set = new HashSet();
Point p1 = new Point(1, 1);
Point p2 = new Point(1, 1); System.out.println(p1.equals(p2));
set.add(p1); //(1)
set.add(p2); //(2)
set.add(p1); //(3) Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
System.out.println(object);
}
}
} class Point {
private int x;
private int y; public Point(int x, int y) {
super();
this.x = x;
this.y = y;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
} @Override
public String toString() {
return "x:" + x + ",y:" + y;
} }
输出
true
x:1,y:1
x:1,y:1
分析
(1)当执行set.add(p1)时(1),集合为空,直接存入集合;
(2)当执行set.add(p2)时(2),首先判断该对象(p2)的hashCode值所在的存储区域是否有相同的hashCode,因为没有覆盖hashCode方法,所以jdk使用默认Object的hashCode方法,返回内存地址转换后的整数,因为不同对象的地址值不同,所以这里不存在与p2相同hashCode值的对象,因此jdk默认不同hashCode值,equals一定返回false,所以直接存入集合。
(3)当执行set.add(p1)时(3),时,因为p1已经存入集合,同一对象返回的hashCode值是一样的,继续判断equals是否返回true,因为是同一对象所以返回true。此时jdk认为该对象已经存在于集合中,所以舍弃。
测试二:覆盖hashCode方法,但不覆盖equals方法,仍然会导致数据的不唯一性
class Point {
private int x;
private int y; public Point(int x, int y) {
super();
this.x = x;
this.y = y;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
} @Override
public String toString() {
return "x:" + x + ",y:" + y;
} }
输出
false
x:1,y:1
x:1,y:1
分析
测试三 内存泄漏问题
public class HashCodeTest {
public static void main(String[] args) {
Collection set = new HashSet();
Point p1 = new Point(1, 1);
Point p2 = new Point(1, 2); set.add(p1);
set.add(p2); p2.setX(10);
p2.setY(10); set.remove(p2); Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
System.out.println(object);
}
}
} class Point {
private int x;
private int y; public Point(int x, int y) {
super();
this.x = x;
this.y = y;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
} @Override
public String toString() {
return "x:" + x + ",y:" + y;
} }
结果
x:1,y:1
x:10,y:10
分析
假设p1的hashCode为1,p2的hashCode为2,在存储时p1被分配在1号桶中,p2被分配在2号筒中。这时修改了p2中与计算hashCode有关的信息(x和y),当调用remove(Object obj)时,首先会查找该hashCode值得对象是否在集合中。假设修改后的hashCode值为10(仍存在2号桶中),这时查找结果空,jdk认为该对象不在集合中,所以不会进行删除操作。然而用户以为该对象已经被删除,导致该对象长时间不能被释放,造成内存泄露。解决该问题的办法是不要在执行期间修改与hashCode值有关的对象信息,如果非要修改,则必须先从集合中删除,更新信息后再加入集合中。
总结
1.hashCode是为了提高在散列结构存储中查找的效率,在线性表中没有作用。
2.equals和hashCode需要同时覆盖。
3.若两个对象equals返回true,则hashCode有必要也返回相同的int数。
4.若两个对象equals返回false,则hashCode不一定返回不同的int数,但为不相等的对象生成不同hashCode值可以提高哈希表的性能。
5.若两个对象hashCode返回相同int数,则equals不一定返回true。
6.若两个对象hashCode返回不同int数,则equals一定返回false。
7.同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题。
原文:https://blog.csdn.net/haobaworenle/article/details/53819838
【Java杂记】Equals 和 hashCode的更多相关文章
- Java:重写equals()和hashCode()
Java:重写equals()和hashCode() 1.何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念). 2.设计equals() [1]使用instan ...
- java中equals和hashCode方法随笔二
前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...
- Java中equals和hashcode的区别?
Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...
- java中equals和hashCode方法的解析
解析Java对象的equals()和hashCode()的使用 前言 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个.在多 ...
- Java实战equals()与hashCode()
一.equals()方法详解 equals()方法在object类中定义如下: 代码 public boolean equals(Object obj) { return (this == obj); ...
- java的equals()与hashCode()以及包装类中的实现
1. hashcode 1.1 hashcode来源 1.2 hashcode的形式 1.3 hashcode目的 1.4 hashcode规则 1.5 hashcode作用体现 1.6 重写hash ...
- java ==、equals、hashcode有什么区别
1.== 用来比较两个对象的存储空间 2.equals是Object类提供的方法之一,每个java类都继承Object类,所以每一个对象都具有equals方法,所以在没有覆盖equals方法的情况下, ...
- java学习-- equals和hashCode的关系
hashcode的目的就是在hashset或者hashmap等中比较两个对象相等时,减少equals的使用次数来提高效率 以下为摘录 java中hashcode和equals的区别和联系 HashSe ...
- Java中equals,hashcode
在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个有符号的32位整数,对 ...
- java重写equals和hashCode方法
一.重写equals方法 如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等. 利用equals比较八大包装对象(如int,f ...
随机推荐
- [boost] : test库
最小化的测试套件minimal_test test库提供一个最小化的测试套件minimal_test, 类似lightweight_test适合入门级测试. 需要包含文件文#include <b ...
- iis运行asp.net页面提示“服务器应用程序不可用”的解决办法_.NET.
原因:主要是iis安装在了net framwork之后 解决办法:需要在IIS中重新注册.net 也就是要用到系统盘: cd c:\windows\microsoft.net\framework\v2 ...
- zabbix监控进程的CPU和内存占用量,进程数量
由于需要对公司特定服务进行监控,于是,通过编写脚本获取各个进程占用系统资源的信息,从而使用zabbix采集到这些数据进行特定进程的基础监控. 我这主要需要监控的程序如下: nginx redis my ...
- spring SOA architecture
在谈这个之前,还得再说下SOA和平台.SOA做两件事情,一个是解耦并识别可重用的服务,一个是对服务进行灵活组装和编排满足业务需求,SOA核心是业务和技术的解耦,服务和能力的复用.而在IT领域的平台平台 ...
- 实验七 c字符数组和字符串函数
7.1 #include<stdio.h>#include<string.h> int main(){ char a[40]; int i; gets(a); //输入字符串进 ...
- 5.验证用户名是否已经被注册:AJAXC请求
首先在 web.xml 文件中添加配置信息 <!-- 配置全局的字符集 --> <context-param> <param-name>encode</par ...
- [转]Java. SqlServer 使用
public void add(Emp emp) throws Exception { String connectionUrl = "jdbc:sqlserver://localhost: ...
- [转]修改DLL
部分内容来自:http://blog.csdn.net/csdncshuan/article/details/51477705 为没有源码的DLL文件添加强名称 如果项目中引用了其他没有源码的dll文 ...
- VBA文本型数字变成数值
sub test()with activesheet .usedrange.numberformatlocal="" .usedrange=.usedrange.valueen ...
- [UE4]蓝图转换成C++代码
版本:4.12 1.进行如下设置 2.将项目打包出来(任意一平台都行,本文以Windows为例) 3.打包完成后才会在原项目工程中生成蓝图转换成c++的代码 4.如图路径(转换后的代码路径较深所以一步 ...