- 浏览: 2191326 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (682)
- 软件思想 (7)
- Lucene(修真篇) (17)
- Lucene(仙界篇) (20)
- Lucene(神界篇) (11)
- Solr (48)
- Hadoop (77)
- Spark (38)
- Hbase (26)
- Hive (19)
- Pig (25)
- ELK (64)
- Zookeeper (12)
- JAVA (119)
- Linux (59)
- 多线程 (8)
- Nutch (5)
- JAVA EE (21)
- Oracle (7)
- Python (32)
- Xml (5)
- Gson (1)
- Cygwin (1)
- JavaScript (4)
- MySQL (9)
- Lucene/Solr(转) (5)
- 缓存 (2)
- Github/Git (1)
- 开源爬虫 (1)
- Hadoop运维 (7)
- shell命令 (9)
- 生活感悟 (42)
- shell编程 (23)
- Scala (11)
- MongoDB (3)
- docker (2)
- Nodejs (3)
- Neo4j (5)
- storm (3)
- opencv (1)
最新评论
-
qindongliang1922:
粟谷_sugu 写道不太理解“分词字段存储docvalue是没 ...
浅谈Lucene中的DocValues -
粟谷_sugu:
不太理解“分词字段存储docvalue是没有意义的”,这句话, ...
浅谈Lucene中的DocValues -
yin_bp:
高性能elasticsearch ORM开发库使用文档http ...
为什么说Elasticsearch搜索是近实时的? -
hackWang:
请问博主,有用solr做电商的搜索项目?
Solr中Group和Facet的用法 -
章司nana:
遇到的问题同楼上 为什么会返回null
Lucene4.3开发之第八步之渡劫初期(八)
在Java里面所有的类都直接或者间接的继承了java.lang.Object类,Object类里面提供了11个方法,如下:
```` 1,clone() 2,equals(Object obj) 3,finalize() 4,getClass() 5,hashCode() 6,notify() 7,notifyAll() 8,toString() 9,wait() 10,wait(long timeout) 11,wait(long timeout, int nanos) ````
这里面我们常用的方法有三个:
```` toString() equals(Object obj) hashCode() ````
toString方法,相信用过Java的人都不会陌生,默认打印的是:类名@十六进制的hashCode,源码中定义如下:
```` public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } ````在经过重写后,我们可以打印一个class的所有属性,这样在打印log或调试时比较方便。
下面重点介绍下hashCode和equals方法:
(1)equals方法,在JDK默认的情况下比较的是对象的内存地址,源码如下:
```` public boolean equals(Object obj) { return (this == obj); } ````
(2)hashcode方法,默认情况下返回的是一个唯一的整数,代表该实例的内存地址,注意这个数字
并不是实际的内存地址,Java是没办法直接获取内存地址的,必须得由C或者C++获取,所以这个方法是用
native修饰的
```` public native int hashCode(); ````
由于默认情况下,equals方法比较的是内存地址,而在实际开发中,我们判断两个对象是否相等,一般都是根据对象的属性来判断的,
所以需要重写这个方法,不然的话,是没办法比较的。举例如下:
定义的类如下:
```` public class Hero { private String id; private String name; public Hero() { } public Hero(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ````直接比较两个对象,结果是不相等的:
```` `````` Hero h1=new Hero("1","张飞"); Hero h2=new Hero("1","张飞"); //false System.out.println(h1.equals(h2)); ````
因为他们的内存地址是不同的,所以结果是false,如果我们想要认为他是相等的,那么就需要重写
equals方法:
```` @Override public boolean equals(Object o) { if (this == o) return true;//如果内存地址相等,则两个对象必定相等 if (o == null || getClass() != o.getClass()) return false;//如果有一个为null或者class不一样,认为必不相等 Hero hero = (Hero) o;// if (id != null ? !id.equals(hero.id) : hero.id != null) return false;//比较id,不相等就返回false return name != null ? name.equals(hero.name) : hero.name == null;//上面的条件通过后比较name,如果相等返回true,不相等返回false } ````
在重写equals方法后,我们在比较两个对象,发现就相等了
```` ``` Hero h1=new Hero("1","张飞"); Hero h2=new Hero("1","张飞"); //true System.out.println(h1.equals(h2)); ````
接着我们看第二个例子,将其放入ArrayList中,然后判断是否存在,发现也生效了:
```` ` Hero h1=new Hero("1","张飞"); List<Hero> heros=new ArrayList<Hero>(); heros.add(h1); //true System.out.println(heros.contains(new Hero("1","张飞"))); ````
到目前为止,我们还没有对hashCode进行操作,那么大家可能会有一个疑问,既然都有equals方法比较了,为啥还需要hashCode方法呢? 别着急,继续看下面的例子:
我们都知道在Java里面HashSet类,去无序去重的,下面看一下,只重写equasl方法能不能实现对class的去重:
```` ` Hero h1=new Hero("1","张飞"); Hero h2=new Hero("1","张飞"); Set<Hero> heros=new HashSet<Hero>(); heros.add(h1); heros.add(h2); //2 System.out.println(heros.size()); //false System.out.println(heros.contains(new Hero("1","张飞"))); ````
从上面的结果看,并没有去重,有的小伙伴会说为啥时string类型的时候就能去重?这是因为Stirng类默认已经重写了equals和hashcode方法,当然所有的基本类型都重写这两个方法了。
接着回到上面的问题,为什么在HashSet中去重失效了呢?
其实,不止是HashSet,在HashMap和Hashtable等等所有使用hash相关的数据结构中,如果使用时不重写hashcode,那么就没法比较对象是否存在。
这其实与HashMap存储原理相关(HashSet底层用的也是HashMap),HashMap在存储时其实是采用了数组+链表的存储结构,数组
中的每一个元素,我们可以理解成是一个buckets(桶),桶里面的结构是链表,而数据是如何分到各个桶里面其实与hashCode有很大关系,只有hashCode一样的
对象才能被分到一个桶里。存的时候,遍历链表判断是否存在,如果存在就不覆盖,如果不存在就把该元素放在链表的头,把next指向上一次的头,而读取的时候先定位到桶里,然后遍历
链表找到该元素即可。
理解了这些,就明白了为啥上面的例子中,去重失效了。就是因为他们的hashCode不一样,导致被分到不同的桶里面了,自然就没法去重了。
重写hashCode之后,再看结果:
```` @Override public int hashCode() { return Integer.parseInt(id); } ````
```` · Hero h1=new Hero("1","张飞"); Hero h2=new Hero("1","张飞"); Set<Hero> heros=new HashSet<Hero>(); heros.add(h1); heros.add(h2); //1 System.out.println(heros.size()); //true System.out.println(heros.contains(new Hero("1","张飞"))); ````
这下结果就对了。
那么问题来了,为啥需要hashCode? 因为在HashSet中,可以存储大量的元素,如果没有hashCode,那么每次就得全量的比较每一个元素,来判断
是否存在,这样以来效率肯定极低,而有了hashCode之后,只需要找到该数据的链表,然后遍历这个链表的数据即可,这样以来效率
就大大提升。
总结:
(1)如果两个对象相等,那么他们必定有相同的hashcode
(2)如果两个对象的hashcode相等,他们却不一定相等
(3)重写equasl方法时,一定要记得重写hashcode方法,尤其用在hash类的数据结构中。
有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。
发表评论
-
记一次log4j不打印日志的踩坑记
2019-09-22 01:58 1600### 起因 前几天一个跑有java应用的生产集群(200多 ... -
在Java里面如何解决进退两难的jar包冲突问题?
2019-07-23 19:10 1262如上图所示: es api组件依赖guava18.0 ... -
如何轻松理解二叉树的深度遍历策略
2019-07-03 23:33 1164我们知道普通的线性数据结构如链表,数组等,遍历方式单一 ... -
为什么单线程Redis性能也很出色
2019-01-21 18:02 2229高性能的服务器,不一 ... -
如何将编程语言里面的字符串转成数字?
2019-01-11 23:23 2118将字符串转成数字在很 ... -
为什么Java里面String类是不可变的
2019-01-06 18:36 1692在Java里面String类型是不可变对象,这一点毫无疑问,那 ... -
关于Java里面volatile关键字的重排序
2019-01-04 18:49 1092Java里面volatile关键字主 ... -
多个线程如何轮流打印ABC特定的次数?
2018-12-11 20:42 6070之前的一篇文章,我给 ... -
聊聊Java里面的引用传递
2018-11-16 21:21 994长久以来,在Java语言里面一直有一个争论,就是Java语言到 ... -
理解计数排序算法的原理和实现
2018-10-11 10:03 2098计数排序(Counting sort) ... -
理解Java7和8里面HashMap+ConcurrentHashMap的扩容策略
2018-09-06 11:31 3396### 前言 理解HashMap和Con ... -
关于Java里面多线程同步的一些知识
2018-07-18 09:45 1113# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
Java单例模式之双检锁深入思考
2018-07-08 12:25 3299# Java单例模式之双检锁 ... -
关于Java里面多线程同步的一些知识
2018-07-08 12:23 1127# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
重新认识同步与异步,阻塞和非阻塞的概念
2018-07-06 14:30 1478# 重新认识同步与异步 ... -
线程的基本知识总结
2018-06-27 16:27 1064### (一)创建线程的方式 (1)实现Runnable接口 ... -
Java里面volatile关键字修饰引用变量的陷阱
2018-06-25 11:42 1393# Java里面volatile关键字修饰引用变量的陷阱 如 ... -
关于Java里面的字符串拼接,你了解多少?
2018-06-25 11:28 1378# 关于Java里面的字符串 ... -
深入理解Java内存模型的语义
2018-06-25 11:39 747### 前言 Java内存模型( ... -
如何证明Java多线程中的成员变量数据是互不可见的
2018-06-21 10:09 1510前面的几篇文章主要介绍了Java的内存模型,进程和线程的定义, ...
相关推荐
Java 中的 hashCode 和 equals 方法详解 本文详细介绍了 Java 中的 hashCode 和 equals 方法,探讨了这两个方法的作用、实现机制和使用场景。通过对 hashCode 和 equals 方法的深入分析,我们可以更好地理解 Java ...
在这篇文章中,我将告诉大家我对hashCode和equals方法的理解。我将讨论他们的默认实现,以及如何正确的重写他们。我也将使用Apache Commons提供的工具包做一个实现。 hashCode()和equals()定义在Object类中,这...
在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将详细介绍这两个方法的工作原理、使用场景以及它们之间的关系...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...
在Java编程语言中,`hashCode()`和`equals()`方法是对象身份验证的关键组成部分,它们主要用于对象的比较和哈希表(如HashMap、HashSet等)的操作。理解这两个方法的工作原理对于编写高效和可靠的代码至关重要。 ...
深入理解Java中HashCode方法 Java中的hashCode方法是每个类都需要实现的重要方法之一,它的主要作用是将对象的数据转换为一个32位的整数,用于标识对象的唯一性。在Java的所有类中,Object类是最顶层的父类,它定义...
在Java编程语言中,`hashCode()` 和 `equals()` 是两个非常重要的方法,它们主要用于对象的比较和哈希表(如HashMap)的操作。标题提到的"HashCode相同equals不同的2位字符集合算法"涉及到的是一个特定场景:两个...
总的来说,理解并正确地重写 `equals()` 和 `hashCode()` 方法是Java编程中的基础技能,它有助于确保对象的比较和集合操作的正确性。在开发过程中,要时刻注意这两个方法的正确实现,以提高代码质量和可维护性。
在Java编程语言中,`hashCode()` 和 `equals()` 方法对于对象的比较和处理至关重要,尤其在集合类(如Set和Map)中。这两个方法都源自`java.lang.Object`类,因此所有的Java类都默认继承了它们。理解并正确地重写这...
在Java编程语言中,`hashCode()`与`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将详细介绍这两个方法的工作原理、使用场景以及在Java集合框架...
为了使对象能够被正确地存储在基于散列的集合(如`HashSet`、`HashMap`)中,`equals`方法和`hashCode`方法必须保持一致。这意味着如果两个对象根据`equals`方法被认为是相等的,那么它们的`hashCode`方法也必须返回...
总的来说,理解并正确使用`equals()`和`hashCode()`方法对于编写高质量的Java代码至关重要,尤其是在处理集合框架中的对象时。这两个方法的合理实现能确保对象比较的正确性和哈希表操作的效率。希望这个深入解析能...
在Java编程语言中,`equals()`和`hashCode()`方法是两个至关重要的概念,它们与对象的比较和哈希表操作紧密相关。理解这两个方法的工作原理及其契约是成为一名熟练的Java开发者所必需的。 首先,`equals()`方法是...
在Java编程语言中,了解如何正确使用`==`和`equals()`方法是非常关键的,因为它们在比较对象和基本类型时有不同的行为。下面将详细解释这两个方法的工作原理、使用场景以及一些常见误区。 首先,`==`运算符主要用于...
总的来说,深入理解并正确实现`equals`方法是Java编程中的基础但关键的技能。这涉及到对Java对象模型的理解,以及如何根据对象的业务逻辑来定义“相等”的概念。通过遵循API规范和良好的编码习惯,我们可以确保`...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的概念,尤其是在处理对象比较和哈希表(如 `HashMap` 和 `HashSet`)时。`equals()` 方法用于判断两个对象是否相等,而 `hashCode()` 方法则用于...
在 Java 中,equals() 方法和 hashCode() 方法是两个紧密相关的方法,它们都是用于比较和标识对象的方法。equals() 方法用于比较两个对象的值是否相等,而 hashCode() 方法用于生成对象的哈希码,以便在散列集合中...
在Java编程中,`hashCode()`、`equals()`以及`==`是三个经常被提及的概念,它们在处理对象的比较和存储时起着关键作用。本文将深入探讨这三个概念的介绍、区别以及它们在Java对象比较中的应用。 首先,`hashCode()`...