- 浏览: 271756 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (133)
- GWT (7)
- IT生活 (9)
- JAVA综合 (38)
- Servlet (5)
- vaadin (2)
- About Eclipse (2)
- StarUML (1)
- Spring (7)
- ibatis (3)
- web (35)
- ExtJs (2)
- Quartz (13)
- Struts (1)
- 学习XML (6)
- io流 (2)
- web应用之压缩 (3)
- Spring MVC (0)
- Velocity (5)
- 静态代码分析工具 (2)
- 观点 (1)
- JUnit (3)
- jQuery (4)
- mysql (2)
- javascript (16)
- linux (4)
- pattern (1)
- java加密技术 (2)
最新评论
-
tan4836128:
确实不行,我的1.8.5,降到1.6.2也不行,楼主的情况很局 ...
Spring调用Quartz定时任务报Couldn't store trigger异常 -
alfusen_xiong:
有没有自动注入的方法可以取代executeInternal() ...
Quartz任务中调用Spring容器中bean及动态调度任务 -
luoxiang183:
换了也不行啊
Spring调用Quartz定时任务报Couldn't store trigger异常 -
liubey:
首先谢谢LZ的文章,其实我想问个问题,既然有心做成工具类,就最 ...
对象和map转换 -
小林夕:
几年前用还行,现在做UML一般都开始使用在线作图工具了,可以了 ...
StarUML简介
经常在论坛上面看到覆写hashCode函数的问题,很多情况下是一些开发者不了解hash code,或者和equals一起用的时候不太清楚为啥一定要覆写hashCode。
对于hash code的理论我不想多说,这个话题太大。那些“对称性”,“传递性”的规则网上有无数的文章来描述。我只想说用hash code的原因只有一个:效率。理论的说法它的复杂度只有O(1)。试想我们把元素放在线性表里面,每次要找一个元素必须从头一个一个的找它的复杂度有O(n)。如果放在平衡二叉树,复杂度也有O(log n)。
为啥很多地方说“覆写equals的时候一定要覆写hashCode”。说到这里我知道很多人知道有个原则:如果a.equals(b)那么要确保a.hashCode()==b.hashCode()。为什么?hashCode和我写的程序的业务逻辑毫无关系,为啥我要override? 要我说如果你的class永远不可能放在hash code为基础的容器内,不必劳神,您真的不必override hashCode()
说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override hashCode了。至于HashSet,实际上它只是忽略value的HashMap,每次HashSet.add(o)其实就是HashMap.put(o, dummyObject)。
那为什么放到Hash容器里面要overide hashCode呢?因为每次get的时候HashMap既要看equals是不是true也要看hash code是不是一致,put的时候也是要看equals和hash code。
如果说到这里您还是不太明白,咱就举个例子:
譬如把一个自己定义的class Foo{...}作为key放到HashMap。实际上HashMap也是把数据存在一个数组里面,所以在put函数里面,HashMap会调Foo.hashCode()算出作为这个元素在数组里面的下标,然后把key和value封装成一个对象放到数组。等一下,万一2个对象算出来的hash code一样怎么办?会不会冲掉?先回答第2个问题,会不会冲掉就要看Foo.equals()了,如果equals()也是true那就要冲掉了。万一是false,就是所谓的collision了。当2个元素hashCode一样但是equals为false的时候,那个HashMap里面的数组的这个元素就变成了链表。也就是hash code一样的元素在一个链表里面,链表的头在那个数组里面。
回过来说get的时候,HashMap也先调key.hashCode()算出数组下标,然后看equals如果是true就是找到了,所以就涉及了equals。
假设如果有个key为a的元素在HashMap里面的情况:
1:如果这时候用equals为true但是hashCode不等的b作为get参数的话,这个时候b算出来的数组下标一定不是a所在的下标位置。
2:如果这时候用equals为false但是hashCode相等的b作为get参数的话,这个时候b算出来的数组下标是对了,但是用equals来寻找相符的key就找不到a了。
以上2种情况要么就是get找不到符合的元素返回null,要么就是返回一个hashCode和equals恰好都符合b的另外的元素,这就产生了混乱。混乱的根本就是错误实现hashCode和equals。
下面有个非常简化版的HashMap实现帮助大家理解,您甚至可以把它当作伪代码来看。(这个实现只是为了模拟HashMap的机制,所以参数检查,访问修饰符都忽略。在java.util.HashMap里面的对hash值的二次hash,根据数组长度计算index,以及超出数组时的resize都忽略)
view plaincopy to clipboardprint?01./* 02. * Just to demonstrate hash map mechanism, 03. * Please do not use it in your commercial product. 04. * 05. * Argument checking and modifier are ignored. 06. * In java.util.HashMap, array are used instead of ArrayList, so index of array is calculated by 'h & (length-1)', 07. * while we use ArrayList to skip the calculation for simple. 08. * 09. * @author Shengyuan Lu 卢声远 <michaellufhl@yahoo.com.cn> 10. */ 11.public class SimpleHashMap { 12. ArrayList<LinkedList<Entry>> entries = new ArrayList<LinkedList<Entry>>(); 13. 14. /** 15. * Each key-value is encapsulated by Entry. 16. */ 17. static class Entry { 18. Object key; 19. Object value; 20. public Entry(Object key, Object value) { 21. this.key = key; 22. this.value = value; 23. } 24. } 25. void put(Object key, Object value) { 26. LinkedList<Entry> e = entries.get(key.hashCode()); 27. if (e != null) { 28. for (Entry entry : e) { 29. if (entry.key.equals(key)) { 30. entry.value = value;// Match in lined list 31. return; 32. } 33. } 34. e.addFirst(new Entry(key, value));// Add the entry to the list 35. } else { 36. // Put the new entry in array 37. LinkedList<Entry> newEntry = new LinkedList<Entry>(); 38. newEntry.add(new Entry(key, value)); 39. entries.add(key.hashCode(), newEntry); 40. } 41. } 42. Object get(Object key) { 43. LinkedList<Entry> e = entries.get(key.hashCode()); 44. if (e != null) { 45. for (Entry entry : e) { 46. if (entry.key.equals(key)) { 47. return entry.value; 48. } 49. } 50. } 51. return null; 52. } 53. 54. /** 55. * Do we need to override equals() and hashCode() for SimpleHashMap itself? 56. * I don't know either:) 57. */ 58.}
对于hash code的理论我不想多说,这个话题太大。那些“对称性”,“传递性”的规则网上有无数的文章来描述。我只想说用hash code的原因只有一个:效率。理论的说法它的复杂度只有O(1)。试想我们把元素放在线性表里面,每次要找一个元素必须从头一个一个的找它的复杂度有O(n)。如果放在平衡二叉树,复杂度也有O(log n)。
为啥很多地方说“覆写equals的时候一定要覆写hashCode”。说到这里我知道很多人知道有个原则:如果a.equals(b)那么要确保a.hashCode()==b.hashCode()。为什么?hashCode和我写的程序的业务逻辑毫无关系,为啥我要override? 要我说如果你的class永远不可能放在hash code为基础的容器内,不必劳神,您真的不必override hashCode()
说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override hashCode了。至于HashSet,实际上它只是忽略value的HashMap,每次HashSet.add(o)其实就是HashMap.put(o, dummyObject)。
那为什么放到Hash容器里面要overide hashCode呢?因为每次get的时候HashMap既要看equals是不是true也要看hash code是不是一致,put的时候也是要看equals和hash code。
如果说到这里您还是不太明白,咱就举个例子:
譬如把一个自己定义的class Foo{...}作为key放到HashMap。实际上HashMap也是把数据存在一个数组里面,所以在put函数里面,HashMap会调Foo.hashCode()算出作为这个元素在数组里面的下标,然后把key和value封装成一个对象放到数组。等一下,万一2个对象算出来的hash code一样怎么办?会不会冲掉?先回答第2个问题,会不会冲掉就要看Foo.equals()了,如果equals()也是true那就要冲掉了。万一是false,就是所谓的collision了。当2个元素hashCode一样但是equals为false的时候,那个HashMap里面的数组的这个元素就变成了链表。也就是hash code一样的元素在一个链表里面,链表的头在那个数组里面。
回过来说get的时候,HashMap也先调key.hashCode()算出数组下标,然后看equals如果是true就是找到了,所以就涉及了equals。
假设如果有个key为a的元素在HashMap里面的情况:
1:如果这时候用equals为true但是hashCode不等的b作为get参数的话,这个时候b算出来的数组下标一定不是a所在的下标位置。
2:如果这时候用equals为false但是hashCode相等的b作为get参数的话,这个时候b算出来的数组下标是对了,但是用equals来寻找相符的key就找不到a了。
以上2种情况要么就是get找不到符合的元素返回null,要么就是返回一个hashCode和equals恰好都符合b的另外的元素,这就产生了混乱。混乱的根本就是错误实现hashCode和equals。
下面有个非常简化版的HashMap实现帮助大家理解,您甚至可以把它当作伪代码来看。(这个实现只是为了模拟HashMap的机制,所以参数检查,访问修饰符都忽略。在java.util.HashMap里面的对hash值的二次hash,根据数组长度计算index,以及超出数组时的resize都忽略)
view plaincopy to clipboardprint?01./* 02. * Just to demonstrate hash map mechanism, 03. * Please do not use it in your commercial product. 04. * 05. * Argument checking and modifier are ignored. 06. * In java.util.HashMap, array are used instead of ArrayList, so index of array is calculated by 'h & (length-1)', 07. * while we use ArrayList to skip the calculation for simple. 08. * 09. * @author Shengyuan Lu 卢声远 <michaellufhl@yahoo.com.cn> 10. */ 11.public class SimpleHashMap { 12. ArrayList<LinkedList<Entry>> entries = new ArrayList<LinkedList<Entry>>(); 13. 14. /** 15. * Each key-value is encapsulated by Entry. 16. */ 17. static class Entry { 18. Object key; 19. Object value; 20. public Entry(Object key, Object value) { 21. this.key = key; 22. this.value = value; 23. } 24. } 25. void put(Object key, Object value) { 26. LinkedList<Entry> e = entries.get(key.hashCode()); 27. if (e != null) { 28. for (Entry entry : e) { 29. if (entry.key.equals(key)) { 30. entry.value = value;// Match in lined list 31. return; 32. } 33. } 34. e.addFirst(new Entry(key, value));// Add the entry to the list 35. } else { 36. // Put the new entry in array 37. LinkedList<Entry> newEntry = new LinkedList<Entry>(); 38. newEntry.add(new Entry(key, value)); 39. entries.add(key.hashCode(), newEntry); 40. } 41. } 42. Object get(Object key) { 43. LinkedList<Entry> e = entries.get(key.hashCode()); 44. if (e != null) { 45. for (Entry entry : e) { 46. if (entry.key.equals(key)) { 47. return entry.value; 48. } 49. } 50. } 51. return null; 52. } 53. 54. /** 55. * Do we need to override equals() and hashCode() for SimpleHashMap itself? 56. * I don't know either:) 57. */ 58.}
发表评论
-
mysql中varchar类型转换Integer
2011-11-24 15:22 1174CAST(varchar字段 AS SIGNED) -
java 添加和清除cookie
2011-10-24 09:38 1985//添加cookie Cookie cookie = new ... -
java cookie操作
2011-10-24 09:34 1389Cookie概念: Cookie的格式实际上是一段纯文 ... -
java保留两位小数点(转)
2011-10-19 15:48 5659java保留两位小数问题: 方式一: 四舍五入 dou ... -
ibatis中批量删除
2011-09-15 10:27 1630Ibatis中批量删除方法: 方法一: 在映射文件中,按如 ... -
Java反射getFields()和getDeclaredFields()的区别
2011-09-05 13:23 1591Java反射 getFields()和getDeclaredF ... -
AES加密算法原理
2011-09-01 15:18 1663AES加密算法原理 随 ... -
Java AES加密实例
2011-09-01 14:30 3377package com.encrypt.hello; i ... -
Quartz任务中调用Spring容器中bean及动态调度任务
2011-08-31 15:09 19708Quartz 是开源任务调度框 ... -
Observer模式
2011-08-23 09:46 985Java深入到一定程度,就不可避免的碰到设计模式(design ... -
Java环境下Memcached应用详解(转)
2011-08-22 10:05 0本文将对在Java环境下Memcached应用进行详细介绍。M ... -
Spring容器详解(转)
2011-08-22 09:53 1229我们在使用ssh整合项目的时候,Spring在其中是一个非常重 ... -
Spring DI(依赖注入) IOC(控制反转) AOP(面向切面编程)
2011-08-22 09:43 2064spring 的优点? 1.降低了 ... -
11款用于优化、分析源代码的Java工具
2011-08-08 15:13 841本文将提供一些工具, ... -
Java编程中影响性能的一些特点
2011-08-08 15:04 727文中将提供一些在Java编程中影响性能的一些特点,为了能够提高 ... -
Velocity基础
2011-08-08 11:01 1751Velocity 基础 Velocity是一个基于java的 ... -
java io经典例子
2011-08-03 14:45 1107IO是JAVASE中非常重要的一块,是面向对象的完美体现,深入 ... -
JUnit4详细教程
2011-08-02 15:36 1180因jdk5中的新特性,JUn ... -
JUnit4注解
2011-08-02 15:31 972JUnit4注解 JUnit4的测试类不用再继承TestCa ... -
JUnit简明手册
2011-08-02 15:29 831用XP进行开发的过程,unit test是必不可少的环节。作为 ...
相关推荐
主要介绍了Java重写equals及hashcode方法流程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
重写equals和hashcode方法,学习和进步
面试官瞬间就饱了,重写equals函数,需要重写hashCode函数吗? 面试官问我,为什么重写equals函数,必须重写hashCode函数,我当时就懵住了。 然后扯天扯地,然后面试官瞬间就饱了,痛定思痛,写下这篇博客 首先看...
但是为什么JavaDoc明确的告诉我们, hashCode()和equals()要一起重写呢?原因是因为,在Java自带的容器HashMap和HashSet中, 都需同时要用到对象的hashCode()和equals()方法来进行判断,然后再插入删除元素,这点...
本文还介绍了定义对象的相等性、实施equals()和hashCode()的需求、编写自己的equals()和hashCode()方法。通过统一定义equals()和hashCode(),可以提升类作为基于散列的集合中的关键字的使用性。
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.
为什么要有 hashCode? 为什么重写 equals() 时必须重写 hashCode() 方法? String String、StringBuffer、StringBuilder 的区别? String 为什么是不可变的? 字符串拼接用“+” 还是 StringBuilder? String#equals...
这里是一个文档,里边讲解了hashCode与equals方法使用,大家要是不明白,可以去看看
主要介绍了Java 覆盖equals时总要覆盖hashcode的相关资料,这里附有实例代码,具有参考价值,需要的朋友可以参考下
如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同!!!! 如果两个对象不同(即用equals比较返回false),那么它们的hashCode值可能相同也可能不同。 如果两个对象的hashCode相同...
2、为什么改写equals()的时候,总是要改写hashCode() 两个原则: hashCode()的返回值和equals()的关系如下: 如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。 如果x.equals(y)返回...
NULL 博文链接:https://zpointer.iteye.com/blog/1058337
解析Java对象的equals()和hashCode()的使用
HashCode相同equals不同的2位字符集合算法 另附ASCII码表
为什么重写equals方法,还必须要重写hashcode方法
equals():反映的是对象或变量具体的值,即两个对象里面包含的值--可能是对象的引用,也可能是值类型的值。 hashCode():计算出对象实例的哈希码,并返回哈希码,又称为散列函数。根类Object的hashCode()方法的...
主要介绍了重写hashCode()和equals()方法详细介绍,涉及重写equals()方法,重写hashCode()方法,重写equals()而不重写hashCode()的风险等相关内容的介绍,具有一定借鉴价值,需要的朋友可以参考下
首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法
Object类是所有Java类的根类,它定义了一些常用的方法,例如equals()、hashCode()、toString()等。本案例代码将详细展示Object类的使用方法,并提供一些实际场景下的案例,以帮助开发者更好地理解和运用这些方法。 ...