关于hashcode 和 equals 的内容总结
第一:equals() 的作用是 表示其他对象是否“等于”这个对象。
在Object源码里面 equals的作用等价于 == 即 用来比较俩个对象的内存地址是否相同
public boolean equals(Object obj) {
return (this == obj);
}
但是一般我们是想用equals来表示 俩个对象的内容是否相同的 所以需要我们去覆盖 equals的方法
以String类 的 equals方法为例 用来比较两个对象的内容是否相同
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
如果自定义的对象在没有重写equals方法的前提下 使用 equals 的话 那么执行的是 == 即比较俩个对象的内存地址是否相同
在重写equals方法的原则 (现在的IDE 基本都可以自动重写 equals方法了 要是没有特殊的需求 可以直接调用 就能使用了 熊重写equals方法的时候 还需要重写 hashcode )
1. 对称性:如果x.equals(y)返回是"true",那么y.equals(x)也应该返回是"true"。
2. 反射性:x.equals(x)必须返回是"true"。
3. 类推性:如果x.equals(y)返回是"true",而且y.equals(z)返回是"true",那么z.equals(x)也应该返回是"true"。
4. 一致性:如果x.equals(y)返回是"true",只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是"true"。
5. 非空性,x.equals(null),永远返回是"false";x.equals(和x不同类型的对象)永远返回是"false"。
第二:hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
关于hashcode 在数据结构的 查找中 有介绍 它的作用是为了 方便查找 查找的时间理论上是0(1) 在一个对象集合中(hashmap hashset ..) 你可以根据一个对象的哈希码 在哈希表上 迅速的找到它所对应的值
那么hashcode 和 equals 有什么联系呢?
为什么在重写equals的时候 一般都是要重写hashcode呢?
其实吧 说有关系也有关系 说没有关系也没有关系
第一: 如果你的这个类是 单单的用来做比较俩者的内容 并不把它们存放到 集合当中(hashmap, hashset。。。。)当中的话 他们是没有任何关系的
第二: 如果你要是把他们存放到 集合当中hashmap, hashset。。。。) 那他们就很有关系了
为什么 ? 这是因为hashcode的设计的目的 决定的 hashcode的 目的 就是为了 在集合中对对象进行查找
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值 详细了解请 参考 public int hashCode()返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
如何要是不理解的话 可以去 看一下 哈希表的作用 哈希表你可以想象为一个数组 那么哈希码就是 数组的坐标 坐标里面的值就时 对象 然后通过哈希吗来访问响应的对象 这样的方式大大的加快了访问速率
由于哈希码生成算法的不同 难免会发生冲突 即内容不同的对象 生成的哈希吗却相同 关于处理冲突的方式 有很多种 这里 这说一种 链地址法
java的 集合(hashmap hashset 采用的就是类似于这样的方法 )
说到这里应该差不多知道 hashcode和 equals的关系了吧 即通过hashcode 定位到 具体的位置 然后通过 equals比较 这个位置的对象的内容是否和原来的相同
从而生成 各种集合操作 如
hashmap中的 get 操作 看源码
public V get(Object key) {
if (key == null)
return getForNullKey();
// 获取key的hash值
int hash = hash(key.hashCode());
// 在“该hash值对应的链表”上查找“键值等于key”的元素
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
put操作 put() 的作用是对外提供接口,让HashMap对象可以通过put()将“key-value”添加到HashMap中。
public V put(K key, V value) {
// 若“key为null”,则将该键值对添加到table[0]中。
if (key == null)
return putForNullKey(value);
// 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。
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;
// 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出!
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} // 若“该key”对应的键值对不存在,则将“key-value”添加到table中
modCount++;
addEntry(hash, key, value, i);
return null;
}
都是 hashcode和equals 的 合并操作
注意 : hashcode的 重写 要使得对象生成的hashcode尽量避免冲突(即重复)
另外 一般
1)、如果两个对象相等,那么它们的hashCode()值一定相同。
这里的相等是指,通过equals()比较两个对象时返回true。
2)、如果两个对象hashCode()相等,它们并不一定相等。
因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。
==================================================================================
补充学习 string 的hashcode
*/
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;
}
最有意思的是 Integer类型的 hashcode的值 就是 内容的值
/**
* Compares this object to the specified object. The result is
* {@code true} if and only if the argument is not
* {@code null} and is an {@code Integer} object that
* contains the same {@code int} value as this object.
*
* @param obj the object to compare with.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
} /**
* Returns a hash code for a {@code int} value; compatible with
* {@code Integer.hashCode()}.
*
* @param value the value to hash
* @since 1.8
*
* @return a hash code value for a {@code int} value.
*/
public static int hashCode(int value) {
return value;
}
关于hashcode 和 equals 的内容总结的更多相关文章
- 重写Java Object对象的hashCode和equals方法实现集合元素按内容判重
Java API提供的集合框架中Set接口下的集合对象默认是不能存储重复对象的,这里的重复判定是按照对象实例句柄的地址来判定的,地址相同则判定为重复,地址不同不管内容如何都判定为不重复,这有时与需求不 ...
- 对hashcode、equals的理解
1.首先hashcode和equals都是java每个对象都存在的方法,因为他们两是Object的方法. 2.hashcode方法默认返回的是该对象内存地址的哈希码,然而你会发现,Object类中没有 ...
- java中hashcode()和equals()的详解
今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashc ...
- Java hashCode() 和 equals()的若干问题
原文:http://www.cnblogs.com/skywang12345/p/3324958.html 本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() ...
- java中的hashcode()和equals()
equals()和hashcode()都继承自object类. equals() equals()方法在object类中定义如下: public boolean equals(Object obj) ...
- Java hashCode() 和 equals()的若干问题解答
本章的内容主要解决下面几个问题: 1 equals() 的作用是什么? 2 equals() 与 == 的区别是什么? 3 hashCode() 的作用是什么? 4 hashCode() 和 equa ...
- 【Java】hashcode()和equals()
大家知道,在集合中判断集合中的两个元素是否相同,依赖的是hashcode()和equals()两个方法. > 一个简单的实验 public class Teacher { private Int ...
- 用HashSet的add方法谈hashcode和equals方法重写
本文主要通过用HashSet的add方法讲一下hashCode和equals方法重写.错误的地方望指正. 1.了解HashSet的add方法 了解一个方法的好办法是看源码,所以先看源码 private ...
- Java中hashcode,equals和==
hashcode方法返回该对象的哈希码值. hashCode()方法可以用来来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的位置,Map在搜索一个对象的时候先通过has ...
随机推荐
- Maven中的SnapShot版本和Release版本
# Maven中的SnapShot版本和Release版本 ## 区别 - SnapShot 快照版本- Release 发布版本 ## 重要区别 - 本地获取这些依赖的机制不同,如果是快照版本,Ma ...
- CentOS 7下安装Redis
1.安装gcc环境 sudo yum install gcc-c++ 2.安装wget sudo yum install wget 3.下载Redis源码包 wget http://download. ...
- [Java复习] 缓存Cache part1
1. 在项目中是如何使用缓存的?为什么要用?不用行不行?用了可能会有哪些不良后果? 结合项目业务,主要两个目的:高性能和高并发.缓存走内存,天然支持高并发. 不良后果: 缓存与DB双写不一致 缓存雪崩 ...
- 静态文件cdn自解析生成相对路径
一.场景和目标: 用户上传一个包含 index.html 的静态资源压缩包,资源内所有文件都是相互依赖的,不需要用户对内部文件内容做任何特殊处理,仅通过服务端逻辑处理达到用户访问 http: ...
- css 命名规范参考[转]
命名空间 另外最好的实践就是当命名你的类名的时候,使用命名空间前缀来进行分类.这些前缀会在你的命名前添加一组字符,但是这个值能立刻标记每一个类的目的,在你看 HTML 或者样式的时候是很需要的.我使用 ...
- 修改NGUI 3.11 的控件 inputfileld hide input 属性bug
1.勾选hideinput属性后,输入中文,会出现,无法显示的问题. 2.勾选hideinput属性后,密码框会出现第一个字母被吃掉的问题 解决方案:控件都不要勾选hideinput属性,代码做如下修 ...
- Redis HashMap 使用
散列类型相当于Java中的HashMap,他的值是一个字典,保存很多key,value对,每对key,value的值个键都是字符串类型,换句话说,散列类型不能嵌套其他数据类型.一个散列类型键最多可以包 ...
- Loaded plugins: fastestmirror, refresh-packagekit, security
问题描述 最近在用Centos 6.7的时候出现了这种情况 Loaded plugins: fastestmirror, refresh-packagekit, security Loading mi ...
- php 的 socket简单原理及实现
什么是socket socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,连接的一端称为一个socket. 因此socket运行是置少有2个端组成,一个为服务端一个为客户端(客户端可以多 ...
- webstorm 2019.1.3 破解
2019.11.28日,已过期,出门右转 https://blog.csdn.net/ft_sunshine/article/details/92065158 1.修改host文件,末尾添加 0.0. ...