程序猿的日常——Java基础之equals与hashCode
equals和hashCode是我们日常开发最常使用的方法,但是因为一般都使用默认的规则,因此也很少会引起关注。不过了解他们的用途和设计的原则,还是会帮助我们更好的设计代码。
equals
equals是java很基础的一个问题,通常都会跟==来做比较。那么看看下面的问题:
int a = 1;
int b = 1;
System.out.println(a==b);//true
Integer a1 = new Integer(1);
Integer a2 = new Integer(1);
System.out.println(a1==a2);//false
System.out.println(a1.equals(a2));//true
这是因为,==比较的是引用,而equals比较的内容,进入到Integer的源码中,就可以看到它其实重写了equals方法:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
说到equals,就不得不说如果我们想要自己重写equasl都需要注意哪些地方。首先就是equals方法的设计需要满足下面几个特性:
- 自反性:对于所有的非null,a=a
- 对称性:a=b,则b=a
- 传递性:a=b,b=c,则a=c
- 一致性:对于没有被修改的ab,如果a=b,则一直a=b
- 非空性:对于任何非Null,a!=null
因此推荐最佳的equals设计方法应该是
@Override
public boolean equals(Object o){
if(o == this)
return true;
if(!(o instanceof XX))
return false;
XX xx = (XX)o;
return xx.x.equals(o.x);//TODO
}
另外,还需要注意的是,如果覆盖了equals方法,那么还需要注意它的hashCode.
hashCode
这个hashCode其实是有特定的使用场景的,比如List或者数组就不会用到hashCode,如果是HashMap、HashSet、HashTale,那么hashCode就十分重要了。
这是因为在类似HashSet的集合中,是需要对元素去重,那么如何判断两个元素是相同的呢?如果每次调用equals,那么代价有点大,这是因为如果对象内部的属性很多,equals一般需要对比每一项。所以就是用hashCode作为对比的方法。
下面看看Hashtable中添加一个元素的逻辑:
public synchronized V put(K key, V value) {
// 检查value是否为空
if (value == null) {
throw new NullPointerException();
}
// 确保key没有在table中
Entry<?,?> tab[] = table;
int hash = key.hashCode();//获取key的hash值
// 通过对table的length取余,确定对应的存储位置
int index = (hash & 0x7FFFFFFF) % tab.length;
// 挨个对比是否相同
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
在HashMap和HashSet中比较类似,都是下面的逻辑:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
可以看到它们都使用了HashCode,只不过是方式方法不一样而已。
在不同的对象中hashCode的生成规则也是不一样的,不过最终的目的都是返回一个int值。比如,在Integer中:
public static int hashCode(int value) {
return value;
}
在String中:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
因此设计hashCode,需要遵循下面的原则:
- 在程序期间,同一个对象调用hashCode,返回的是一个数
- 如果x.equals(y)返回true,那么它们的hashCode肯定也相等
- 如果x.equals(y)返回false,那么它们的hashCode有可能相等,也有可能不相等。
换句话说,判断两个对象是否相等:
- 如果他们的hashCode不相等,那么它们肯定不想等;如果相同,还得对比equals
- 如果两个对象的equals方法不同,那么对象就不同;否则,对象相同
程序猿的日常——Java基础之equals与hashCode的更多相关文章
- 程序猿的日常——Java基础之抽象类与接口、枚举、泛型
再次回顾这些基础内容,发现自己理解的又多了一点.对于一些之前很模糊的概念,渐渐的清晰起来. 抽象类与接口 抽象类通常是描述一些对象的通用方法和属性,并且默认实现一些功能,它不能被实例化.接口仅仅是描述 ...
- 程序猿的日常——Java基础之clone、序列化、字符串、数组
其实Java还有很多其他的基础知识,在日常工作技术撕逼中也是经常被讨论的问题. 深克隆与浅克隆 在Java中创建对象有两种方式: 一种是new操作符,它创建了一个新的对象,并把对应的各个字段初始化成默 ...
- 程序猿的日常——Java中的集合列表
列表对于日常开发来说实在是太常见了,以至于很多开发者习惯性的用到数组,就来一个ArrayList,根本不做过多的思考.其实列表里面还是有很多玩法的,有时候玩不好,搞出来bug还得定位半天.所以这里就再 ...
- Java基础之equals() 和 hashCode()
equals()是Object中的一个方法: public boolean equals(Object obj) { return (this == obj); } 在Object中equals()方 ...
- Java基础系列-equals方法和hashCode方法
原创文章,转载请标注出处:<Java基础系列-equals方法和hashCode方法> 概述 equals方法和hashCode方法都是有Object类定义的. publi ...
- Java中的equals和hashCode方法
本文转载自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要 ...
- Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)
Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例 原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...
- java中间==、equals和hashCode差额
java于==.equals().hashCode()和比较两个对象. 关于== ==是easy理解的.java设计java就是要比較两个对象是不是同一个对象. 对于引用变量而言.比較的时候两个引用变 ...
- Java中的equals和hashCode方法详解
Java中的equals和hashCode方法详解 转自 https://www.cnblogs.com/crazylqy/category/655181.html 参考:http://blog.c ...
随机推荐
- Scrum 项目1.0--软件工程
1.确定选题 视频:http://v.youku.com/v_show/id_XMTU1OTExOTY2NA==.html 2.需求分析调查 地址:http://www.sojump.com/m/81 ...
- mysql对emoji的支持
步骤: 升级mysql数据库到5.5.3+ 修改database.table和column字符集 alter database DATABASE_NAME character set = utf8mb ...
- Vue.js 登录注册实现
转载 http://www.jb51.net/article/118003.htm
- js导出到word、json、excel、csv
tableExport.js ///*The MIT License (MIT) //Copyright (c) 2014 https://github.com/kayalshri/ //Permis ...
- Devexpress VCL Build v2013 vol 13.2.4 发布
不说了,自己看吧. What's New in 13.2.4 (VCL Product Line) New Major Features in 13.2 What's New in VCL Pro ...
- 2018.10.14 NOIP训练 猜数游戏(决策单调性优化dp)
传送门 一道神奇的dp题. 这题的决策单调性优化跟普通的不同. 首先发现这道题只跟r−lr-lr−l有关. 然后定义状态f[i][j]f[i][j]f[i][j]表示猜范围为[L,L+i−1][L,L ...
- EXT combobox 二级连动 清空store缓存数据
项目中有这样的一个需求,做一个连动操作,如图: 所属行业中的combobox中下拉框中的值会根据前一个选择框中的值动态去变化,这个其实非常好做,但不是我现在讨论的主要问题,主要问题是,当第二次选择了& ...
- 1024 Hello World
哈哈,原来今天是程序员的节日啊,快乐咯,可是今天好冷好冷~~
- Linux下安装配置 Jdk1.6+Tomcat6+Apache2.2.x+jk_mod1.2 详解
本篇以Redhat AS5,内核为Linux 2.6.18-8.el5 为例,其中Redhat/Fedora系列基本一致,其他Linux或者版本均可以参考. STEP 1 软件下载:1. jdk1.6 ...
- Linux将程序添加到服务的方法(通用)
一:咱们通过这篇文章来演示怎么将某个程序作为服务(就类似Windows服务可以开机自动启动),这里以tomcat为例,已经亲测过: 二:步骤(最好用root用户来做这种事情,切换root用户记得su ...