甚是悲哀,工作都已经两年半了,对hashcode和equals还是似懂非懂...
这两天决定找些资料来研究研究,如下即是个人理解,欠妥之处请批评指正。
1.在java里面,默认情况下所有的类都会继承Object类。所以,我们先开始了解Object类里面的
hashcode与equals方法。
public native int hashCode();//调用java里面的本地方产生哈希码
public boolean equals(Object obj) {//这里比较对象地址
return (this == obj);
}
public String toString() {//默认的toString方法与哈希码相关
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
2.下面代码证明Object类产生的哈希码不是内存地址
ArrayList list = new ArrayList();
int numberExist = 0;
// 证明hashcode的值不是内存地址
for (int i = 0; i < 10000; i++) {
Object obj = new Object();
if (list.contains(obj.toString())) {//判断对象哈希码
System.out
.println(obj.toString() + "exists in the list. " + i);
numberExist++;
} else {
list.add(obj.toString());
}
}
System.out.println("repetition number:" + numberExist);
System.out.println("list size:" + list.size());
运行后,发现不同对象哈希码相同了,所以得出哈希码不是内存地址,否则哈希码是不会相同了。
3.下面代码证明Object类的equals方法比较的是内存地址
numberExist = 0;
list.clear();
for (int i = 0; i < 10000; i++) {
Object obj = new Object();
if (list.contains(obj)) {//对象判断,contains方法调用equal
System.out.println(obj + " exists in the list. " + i);
numberExist++;
} else {
list.add(obj);
}
}
System.out.println("repetition number:" + numberExist);
System.out.println("list size:" + list.size());
运行后得出结论,Object类的equals比较的对象的内存地址。
4.所以,从上面的例子看出,Object类的hashcode是这样一个机制。
举个例子来说,比如现有数据1 2 3 4 5 产生了不同的哈希码,现在又有数据6 7 8 9 10数据存储,假设hashcode根据某一机制产生与1 2 3 4 5一一对应的哈希码,那么现在,我们有理由相信,1和6的哈希码因为相同,2和7的哈希码相同...所以就有了一个桶的概念,即1和6同属于一个哈希链,这条链的哈希码是相同的;哈希码相同,那么怎么判断同一个桶里面的对象是否相等的?自然而然,那是equals的用处了。
简言之,hashcode是将对象按一定机制散列到内存归桶,而equals则在判断同一个桶里的对象是否相同。
5.那么哈希码是用来干什么的呢?用来提高查询效率的。比如有12345678910个数,如果现在要找10这个数字,那么常规数组的话,需要比较10次,而用哈希码即到对应的桶查找,有就比较,没有就返回就可以了。效率明显高了。
6.下面看个例子,自己可以通过注释掉hahscode equals方法试着运行
public class Test {
public static void main(String[] args) {
Map m = new HashMap();
m.put(new PhoneNumber(020, 12345678), "shellfeng");
System.out.println(m.get(new PhoneNumber(020, 12345678)));
}
private static class PhoneNumber {
private short areaCode;
private short extension;
public PhoneNumber(int areaCode, int extension) {
this.areaCode = (short) areaCode;
this.extension = (short) extension;
}
public boolean equals(Object o) {//在桶里查找对象,按自己设定规则
if (o == this) {
return true;
}
if (!(o instanceof PhoneNumber)) {
return false;
}
PhoneNumber pn = (PhoneNumber) o;
return pn.extension == extension && pn.areaCode == areaCode;//桶类型对象判断是否相同的规则
}
public int hashCode() {//将对象归类,即分属于不同的桶,如改为return 1则意味着所有对象放一号桶
int result = 17;
result = 37 * result + areaCode;
result = 37 * result + extension;
return result;
}
}
}
一般地说,hashcode和equals方法要么同时重写,要么同时覆盖。
如上例,重写任何一方都没多大意义。
7.有个规则:a.equals()=b.equals(),那么,a.hashcode()=b.hashcode()
a.hashcode()!=b.hashcode(),那么,a.equals!=b.equals()
8.查看Integer源码发现,equals和hashcode都与Integer的值相关,即可以看出
只要是数值不相等的两个数,hashcode和equals都不一样,所以hashcode这个桶(哈希链)概念就没什么意思了。
9.一般数组与hashcode散列的效率
public class Test {
public static void main(String[] args) {
Integer[] datas = new Integer[2000000];
Map<Integer,Integer> map= new HashMap<Integer,Integer>();
for (int i = 0; i < datas.length; i++) {
datas[i] = i;
map.put(i, i);
}
long t1 = new Date().getTime();
for (int i = 0; i < datas.length; i++) {
if (datas[i] == 1888888) {
break;
}
}
//System.out.println("----------->"+ map.get(1888888));
long t2 = new Date().getTime() - t1;
System.out.println("----------->" + t2);
}
}
分享到:
相关推荐
HashCode相同equals不同的2位字符集合算法 另附ASCII码表
equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.
这里是一个文档,里边讲解了hashCode与equals方法使用,大家要是不明白,可以去看看
hashcode、equals、==总结1简单总结.txt,他们之间的区别
本文档详细介绍了set接口为什么会用到hashCode和equals方法以及这两个方法的一些探讨 set不同的实现类用到的这两个方法也不同
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
java中hashcode和equals的详解.pdf
在这篇文章中,我将告诉大家我对hashCode和equals方法的理解。我将讨论他们的默认实现,以及如何正确的重写他们。我也将使用Apache Commons提供的工具包做一个实现。 hashCode()和equals()定义在Object类中,这...
主要介绍了重写hashCode()和equals()方法详细介绍,涉及重写equals()方法,重写hashCode()方法,重写equals()而不重写hashCode()的风险等相关内容的介绍,具有一定借鉴价值,需要的朋友可以参考下
文章目录1、hashCode与equals两者之间的关系2、== 和equals的区别`3、为什么要重写equals()方法?4、重写equals()方法5、为什么要重写hashCode()方法?6、什么时候需要重写hashCode()方法?7、重写hashCode()方法: ...
有许多人学了很长时间的Java,但一直不明白hashCode方法的作用,我来解释一下吧。首先,想要明白hashCode的作用,你必须要先知道Java中的集合。
重写equals和hashcode方法,学习和进步
关于hashCode()和equals()的本质区别和联系.doc
本文还介绍了定义对象的相等性、实施equals()和hashCode()的需求、编写自己的equals()和hashCode()方法。通过统一定义equals()和hashCode(),可以提升类作为基于散列的集合中的关键字的使用性。
hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法。下面这篇文章主要给大家介绍了关于java中hashCode、equals的使用方法,需要的朋友可以参考下。
更清楚的了解hashcode()和equals()方法。
hashcode()和equals() 博客地址:https://blog.csdn.net/qq_36963950/article/details/107543471
NULL 博文链接:https://zpointer.iteye.com/blog/1058337
1、何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念)。 2、为什么改写equals()的时候,总是要改写hashCode() ... 3、什么是equals()与如何设计equals()