`
Heis
  • 浏览: 114403 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

大话深入浅出Effective Java核心实战编程思想之——那些鸡翅

阅读更多

好吧好吧,我承认这有点标题党的嫌疑,我这不是隔太久没更新,有点兴奋么。
    板砖拍够了,臭鸡蛋扔够了,别来打酱油便行了。我这就进入正题。其实正确的标题应该叫Effective Java读书心得之鸡翅的故事。

    关于鸡翅的故事,相传最近最近以前……

 1  import  static  org.junit.Assert. * ;
 2  
 3  import  java.util.HashMap;
 4  
 5  import  org.junit.Test;
 6  
 7  
 8  public  class  TestObjectHashCode {
 9      
10      @Test
11       public  void  testIt(){
12             // 最近,麦当当推出了麦香翅,味道不是一般的好,那是相当的好。
13             // 于是受到消费者的青睐,大受欢迎。
14            鸡翅 麦香翅 = new  鸡翅( " 麦香翅 " );
15            味道 味道好极了 = new  味道( " 味道好极了 " );
16            HashMap 市场 = new  HashMap();
17            市场.put(麦香翅, 味道好极了);
18            
19             // 这一切都被一个山寨小食店看在眼里,他们决定打着麦香翅的名号,推出实际上味道一般的山寨麦香翅
20            鸡翅 山寨麦香翅 = new  鸡翅( " 麦香翅 " );            
21            
22             // 山寨小食店的师傅还是很有智慧的,他们通过某某方式,通过ISO叉叉叉叉的认证。
23             // 他们很天真地认为他们的山寨翅可以媲美麦香翅。
24            assertTrue(山寨麦香翅.equals(麦香翅)); 
25            
26             // 但是结果大家都知道了,山寨翅并没有获得市场的认可,鱼目混珠终究被市场识别出来。
27            assertFalse(味道好极了.equals(市场.get(山寨麦香翅)));
28            
29             // 山寨小食店苦思瞑想,终于发现了问题,原来他们指打相同的名号是不行的。
30             // 他们的并没有山寨出麦香翅代号为HashCode的秘制酱料
31            assertFalse(麦香翅.hashCode() == 山寨麦香翅.hashCode());         
32      }
33      
34       public  static  final  class  味道{
35             private  String description;
36  
37             public  味道(String des){
38                  description = des;
39            }
40            
41             public  String getDescription() {
42                   return  description;
43            }
44  
45             public  void  setDescription(String aDes) {
46                   this .description  =  aDes;
47            }
48            
49      }
50  
51       public  static  final  class  鸡翅 {
52  
53           private  String Name;
54  
55           public  鸡翅(String name){
56                 this .Name = name;
57          }
58          
59           public  String getName() {
60                 return  Name;
61          }
62  
63           public  void  setName(String aName) {
64                 this .Name  =  aName;
65          }
66          
67          @Override
68           public  boolean  equals(Object obj){
69                 if ( ! (obj  instanceof  鸡翅)){
70                       return  false ;
71                }
72                 return  ((鸡翅)obj).getName().equals( this .Name);
73          }
74    }
75  
76  }
77  

    看完了不知道我想说啥?看来没认真看《Effective Java》嘛,这本书可是每个java程序员进阶必修之书,没看过真不能自称大虾级别。好了,这里说到了正题的正题,其实我想说的是:

《Effective Java》第八条:改写equals时总是要改写hashCode。


*为什么要改写hashCode
答:(书上原话)“如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类在一起正常工作,这样的集合类包括HashMap,HashSet和Hashtable.

*那么为什么会导致该类无法与所有基于散列值(hash)的集合类在一起正常工作呢?
答:且看一个HashMap的源代码解释。

HashMap是通过一个叫table[]的数组来存取,table的每个元素是一个链表结构,链表的每个元素称为 Entry<key,value>,是真正存放key和value的对象。在put的过程中,HashMap会通过特定的哈希算法将key对象的hashCode对应到table的某个索引下,然后再用key对比链表中每个Entry.key,如果key相同则更新value。否则就加入新的 Entry到链表中。

<meta name="ProgId" content="Word.Document"> <meta name="Generator" content="Microsoft Word 11"> <meta name="Originator" content="Microsoft Word 11"> <link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml">

HashMap 的数据结构图:




再看一段HashMap的源代码:

 1  public  V put(K key, V value) {
 2      K k  =  maskNull(key); //  如果key为null则使用缺省的Object
 3           int  hash  =  hash(k); // 将k的hashCode经过一定的计算得到新的HashCode
 4           int  i  =  indexFor(hash, table.length); // 取得HashCode在table中的位置
 5  
 6         // 首先在数组内根据key的HashCode找到Entry链表的第一个Entry        
 7           for  (Entry < K,V >  e  =  table[i]; e  !=  null ; e  =  e.next) {
 8           // 如果Entry的key值HashCode相同,而且具有相同的引用或逻辑相等(equals)
 9               if  (e.hash  ==  hash  &&  eq(k, e.key)) {
10               // 将新的value放入Entry中,返回旧的value
11                  V oldValue  =  e.value;
12                  e.value  =  value;
13                  e.recordAccess( this );
14                   return  oldValue;
15              }
16          }
17        
18           // 修改次数加1
19          modCount ++ ;
20         // 在table的第i个位置的链表后加上一个新的Entry
21          addEntry(hash, k, value, i);
22           return  null ;
23  }
24  
25  static  boolean  eq(Object x, Object y) {
26           return  x  ==  y  ||  x.equals(y);
27      }
28  


*最后来看java.lang.Object的约定(经过自己语言描述,原话自己看书去)
1.如果一个类的equals方法所用到的信息(逻辑相等的条件因素)没有被修改的话,那么它hashCode也不会改变。换个角度来看,也就是说,hashCode返回值最好与equals方法所用到的信息相关。

2.如果两个实例根据equals对比是相等的,那么它们的HashCode相等。

3.如果两个实例根据equals对比是不相等的,那么它们的HashCode最好是不等,这对于Hash性能的提高有好处。

E.g 如果Person实例的ID属性没有被修改的话,那么它的HashCode也不会改变

 1  public  class  Person{
 2           private  String ID;
 3           public  boolean  equals(Object obj){
 4                if ( ! (obj  instanceof  Person) &&  ((Person)obj).getID() != null ){
 5                   return  false ;
 6          }
 7               return  ((Person)obj).getID().equals( this .ID);
 8          }
 9  
10           public  int  hashCode(){
11               if (ID == null ){
12                   return  23 ;
13              } else {
14                   return  ID.hashCode();
15              }
16          }
17           public  String getID() {
18               return  ID;
19          }
20           public  void  setID(String id) {
21              ID  =  id;
22          }
23          
24  }
25  
0
0
分享到:
评论

相关推荐

    java版大话西游源码

    《Java版大话西游源码》是一款基于Java编程语言开发的角色扮演游戏(RPG)教程,对于初学者和想要深入理解游戏开发的程序员来说,它提供了丰富的学习资源。这款教程涵盖了多线程技术和自动寻路算法等核心概念,是...

    OpenFaaS实战之五:大话watchdog(csdn)————程序.pdf

    本文《OpenFaaS实战之五:大话watchdog》重点讨论了OpenFaaS的关键组件watchdog的原理和应用。 在OpenFaaS中,当外部请求到达API Gateway时,它会将请求转发到faas-netes组件。faas-netes作为服务提供者,不仅支持...

    大话核心网.mobi

    大话核心网.mobi

    大话JAVA:从零基础到数据库、WEB开发.

    大话Java:从零基础到数据库、Web开发为所有打算深入掌握Java编程的读者编写,适用于初中级程序开发者,没有接触过Java语言的入门者也可以轻松地阅读《大话Java:从零基础到数据库、Web开发》。

    大话存储终极版——扫描件

    《大话存储终极版》是IT领域内一本深受读者喜爱的存储技术图书,作者冬瓜哥(张冬)以其通俗易懂的语言,深入浅出地介绍了存储领域的诸多知识。这本书对于初学者来说是一份非常宝贵的资源,可以帮助他们快速入门并...

    框架封装1.0版本 大话C#之实践场景入门进阶必知点a,深入浅出解析教程

    标题中的“框架封装1.0版本 大话C#之实践场景入门进阶必知点a,深入浅出解析教程”表明这是一个关于C#编程语言的教程,特别关注于实践场景的应用,适合初学者和进阶者。这个教程可能包含了对C#基础的巩固以及高级...

    【资源免费下载】Java代码积累丨大话设计模式(Java实现版本)、线程协作

    Java代码加速器 Java代码积累:并发 设计模式 数据结构 使用容器 实用 类 基础知识 并发性 演示线程的生命周期 生产者-消费者 设计模式参考《大话设计模式》 工厂简单模式 创造型模式 工厂方法模式 抽象工厂模式 ...

    基于《大话设计模式》的Java设计模式学习源码实战

    该项目是一个基于《大话设计模式》的Java设计模式学习源码实战,包含41个文件,其中36个为Java源文件,4个为Markdown文档,以及1个LICENSE文件。通过实际编码实践,帮助开发者深入理解并掌握设计模式的应用。

    大话JAVA性能优化

    《大话JAVA性能优化》这份文档深入探讨了Java程序在多个层面的性能调优策略,旨在帮助开发者提高程序运行效率,降低资源消耗,提升用户体验。以下是对这些知识点的详细阐述: 1. **代码层次优化**:在代码编写阶段...

    java后端学习推荐书籍清单

    《深入浅出Spring Boot2》《图解Java多线程设计模式》 《深入理解Java虚拟机:JVM高级特性与最佳实践》 《深入理解计算机系统(原书第三版》《Netty权威指南 第2版》 《Netty 4核心原理与手写RPC框架实战》 ...

    Android之大话设计模式——:抽象工厂模式借鉴.pdf

    Android之大话设计模式——:抽象工厂模式借鉴.pdf

    大话JAVA性能优化.pdf

    通读《大话Java性能优化》后,读者可以深入了解Java性能调优的许多主题及相关的综合性知识。读者也可以把《大话Java性能优化》作为参考,对于感兴趣的主题,直接跳到相应章节寻找答案。 总的来说,性能调优在很大...

    大话数据分析:Tableau数据可视化实战----数据集

    总的来说,通过《大话数据分析:Tableau数据可视化实战》的数据集,学习者可以深入实践如何加载数据、构建视图、创建交互式仪表板,并用Tableau来解答业务问题。这涵盖了从数据导入、数据探索、可视化设计到故事呈现...

    大话java性能优化 周明耀 完整版

    《大话java性能优化》是周明耀先生的一本深入探讨Java性能调优的专业书籍,其主要内容涵盖了Java程序设计中的各种性能优化策略和技术。这本书旨在帮助开发者理解和掌握如何提升Java应用的运行效率,减少资源消耗,...

    大话java性能优化

    大话java性能优化,大家可以搜一下这本书。这个是完美中文版,建议下载

    Android之大话设计模式——:抽象工厂模式参考.pdf

    Android之大话设计模式——:抽象工厂模式参考.pdf

    大话Java性能优化

    本书 主要 提供 Java 性能 调 优 方面 的 参考 建议 及 经验交流。 作者 力求 做到 知识 的 综合 传播, 而 不是 仅仅 只 针对 Java 虚拟 机 调 优 进行 讲解, 另外 力求 每一 章节 都有 实际 的 案例 支撑。 具体 ...

    大话Java性能优化.epub

    大话java性能优化,pdf版!

Global site tag (gtag.js) - Google Analytics