Effective Java读书笔记、感悟——2.2 其余Object通用方法
来源:互联网 发布:狙击精英4 知乎 编辑:程序博客网 时间:2024/05/02 00:21
最近一直在忙着完成作业,看书和写博客的进度大大受到折扣。假期回去把最近Nachos的实验重新做一遍,好好总结、测试过后写份博客,中间还是学到了很多东西,虽然学不到什么API的使用。不多说了,继续Java,这才是正道(要遭批斗的言论)。这次的博客中有很多问题都没有注意到,只是做了简单的笔记记录和一些小地方的注释,着重说明了hashCode,尤其clone没有更深入的探究,但是使用过程中有时候只是简单的clone,所以尽量也使用的时候详细的阅读以下该类的clone注释(还有个原因是clone使用需要谨慎,书中提出了推荐的方法,由于最近时间紧张也就没有选择深入探究clone)。
二:覆盖equals时总要覆盖hashCode
Object规范中提到:(非原文,仅理解和摘要)
à执行期间对象的equals比较操作用到的信息没有被修改,那么调用多次hashCode应该始终返回同一个整数,多次运行可以不同。
à两个对象根据equals比较相等,那么他们的hashCode返回相同的值。
àequals不等,hashCode不一定不等,但是给完全不同的对象产生不同的散列码提高性能
如果没有覆盖hashCode而违反的关键约定是第二条。
如果试图和HashMap(在应用程序中被非常广泛的用到)、HashSet、Hashtable一起使用作为key(作为key之后会根据key产生的hashcode进行散列,如果很多不同的对象返回了相同的key就将散列表变成了很少的长链表,降低性能),不保证hashCode被覆盖将带来问题。
书中提到的散列函数(可以在其他自己需要构造散列表的时候使用):
1、把某个非零的常数值,比如说17,保存在一个名为result的int类型的变量中。
2、对于对象中每个关键域f(指equals方法中涉及的每个域),完成以下步骤:
a. 为该域计算int类型的散列码c:
i. 如果该域是boolean类型,则计算(f ? 1 : 0)。
ii. 如果该域是byte、short、char或者int类型,则计算(int)f。
iii. 如果该域是long类型,则计算(int)(f ^ (f >>> 32))。
iv. 如果该域是float类型,则计算Float.floatToIntBits(f)。
v. 如果该域是double类型,则计算Double.doubleToLongBits(f),然后照2.a.iii。
vi. 如果该域是一个对象引用,并且该类的equals方法通过递归地调用equals方法来比较这个域,则同样为这个域递归地调用hashCode。如果需要更复杂的比较,则为这个域计算一个范式,然后针对这个范式调用hashCode。如果这个域的值为null,则返回0。
vii. 如果该域是一个数组,则需要把每一个元素当做单独的域来处理,也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤2.b中的做法把这些散列值组合起来。如果数组域中的每个元素都很重要,可以利用发行版本1.5中增加的其中一个Arrays.hashCode方法。
b. 按照下面的公式,把步骤2.a中计算得到的散列码c合并到result中:result = 31 * result + c ;
3、返回result。
4、写完了hashCode方法之后,问问自己“相等的实例是否都具有相等的散列码”。
之所以采用31是因为它是一个奇素数。如果乘数是偶数,并且惩罚溢出的话信息会丢失,因为与2相乘等于移位运算。使用素数的好处并不明显大,但是习惯使用素数计算散列结果。31还有一个很好的特性,即用移位和减法来代替乘法可以得到更好的性能:31*i==(i<<5)-I。现代的VM可以自动完成这种优化。合理利用移位操作提高效率是好的编程习惯。
这里先从外围,举最常用的Java的HashMap来说明一下HashCode的作用:
下面是put方法,其中是根据用户的hashCode产生的值的基础上做了一次散列计算。用户散列函数效果太差会直接影响到HashMap的使用性能。(尤其我们经常会将自己编写的Bean等作为value传入,如果没有覆盖hashCode)
- Effective Java读书笔记、感悟——2.2 其余Object通用方法
- Effective Java读书笔记、感悟——2.1对所有对象都通用的方法之equals
- Effective Java读书笔记(二):方法、通用程序设计
- 《Effective java》读书笔记3——覆盖equals方法的通用约定
- Effective Java读书笔记——第三章 对于所有对象都通用的方法
- Effective Java——对象通用方法
- Effective Java读书笔记——第八章 通用程序设计
- effective Java读书笔记-通用程序设计
- Effective Java——对所有对象通用的方法
- Effective Java读书笔记、感悟——3.类和接口(一)
- Effective Java读书笔记、感悟——1.创建和销毁对象
- 《Effective java》—–读书笔记
- 《Effective java》—–读书笔记
- 《Effective java》读书笔记6——方法重载
- Effective Java读书笔记——第七章 方法
- 覆盖equals时请遵守通用约定——Effective Java 读书笔记
- 《Effective Java》读书笔记——覆盖equals时请遵守通用约定
- 【读书笔记】《Effective Java》(7)--通用程序设计
- struts 前后台参数交互
- Willlam Shakespeare——5、The plague years
- fortran Because of COMMON, the alignment of object is inconsistent with its type
- JS对文件大小的格式化等
- java 对象深拷贝通用方法
- Effective Java读书笔记、感悟——2.2 其余Object通用方法
- emacs中gdb
- JAVA中文字符编码
- java 解析Json格式数据
- JAVA经典算法40题(16)
- 积累
- java spi 机制
- for test
- JVM调优