用自定义类型作为HashMap或Hashtable的key

HashMap 和 Hashtable 时用来存放键值对的一种容器,不能存储重复的键。若有重复,则覆盖原来的映射关系。

HashMap添加元素的操作过程:

首先,调用key的hashCode( ) 方法生成一个 hash 值 h1,如果在HashMap中不存在,则直接将<key, value>添加到HashMap中;如果这个 h1 已经存在,则找出HashMap中所有hash值为 h1 的key,然后分别调用 key 的equals( )方法来判断添加的key与已经存在的key是否相同。如果equals( )返回true,那么会使用新的 value 覆盖原来的 value 值;如果返回 false ,说明新增加的 key 在HashMap中不存在,因此会在HashMap中建立新的映射关系。

当新增的key的hash值已经存在时,就会产生冲突(一般不同的key值也可能产生相同的hash值),解决冲突的方法有:开放地址法、再hash法、链地址法等。HashMap采用的是链地址法。

结论:

在使用自定义类作为HashMap的key时,需要注意一下几个问题:

(1)如果想根据对象的相关属性来自定义对象是否相等的逻辑,需要重写equals( )方法,一旦重写了equals( ) 方法,就必须重写 hashCode( ) 方法。

(2)当自定义类的多项作为 HashMap(Hashtable)的 key 时,最好把这个类设计成 不可变类(设计不可变类,见下面补充)。

(3)从HashMap的工作原理看,如果两个对象相等,那么这两个对象有着相同的hashCode值,反之不成立。

补充:如何设计不可变类

Java中如何设计不可变类:

  1. 不提供setter方法,setter方法用于修改属性和对象引用 
    这个原则阐述了在你类定义的所有可变属性中,不提供setter方法,setter方法意味着你能够改变这个属性的状态。必须阻止提供setter方法
  2. 所有的属性修饰添加private和final 
    这是另外一种增加不可变的方式,属性声明为private为了在类之外不能够被访问到,final修饰符为了让你不能随便的改变它们
  3. 不允许子类重写方法 
    最简单的方式声明类为final,final类不允许被重写
  4. 当属性中存在可变对象变量时,要特别留意 
    永远铭记你的对象变量,不是可变的就是不可变的(这句好像是废话。。),识别出来可变对象,对可变对象的内容进行copy,并创建一个新对象赋值给它,这样保证可变对象的不可变,通过直接copy对象内容的形式,保持数据不可变
  5. 来点优雅的,定义一个private的构造方法,通过 工厂方法构造对象

猜你喜欢

转载自blog.csdn.net/u012005549/article/details/82789872