HashMap与LinkedHashMap重要知识点

来源:互联网 发布:淘宝双十一营销案例 编辑:程序博客网 时间:2024/06/06 14:02

HashMap:

1.99%的情况下,当你覆盖了equals方法后,请务必覆盖hashCode方法.
 hashCode方法的定义用到了native关键字,表示它是由C或C++采用较为底层的方式来实现的,你可以认为它返回了该对象的内存地址;而缺省equals则认为,只有当两者引用同一个对象时,才认为它们是相等的。如果你只是覆盖了equals()而没有重新定义hashCode(),在读取HashMap的时候,除非你使用一个与你保存时引用完全相同的对象作为key值,否则你将得不到该key所对应的值。

2.HashMap存取机制
Hashmap实际上是一个数组和链表的结合体
对于相同hashCode的不同key,再调用其equals方法从List中提取出和key所相对应的value。
默认情况下initialCapacity为16,loadFactor为0.75.
因为元素的最终位置是其hashCode对key空间长度取模而得
hashMap其key空间的长度一定为2的N次方, 即使我们在构造函数中指定的initialCapacity不是2的平方数,capacity还是会被赋值为2的N次方。
而当除数为2的N次方时,取模运算将退化为最简单的位运算,其效率明显提升 。
为了充分利用高位信息,采用“防御性编程”的解决方法,在使用各对象的hashCode之前对其进行二次Hash。

3.Fail-Fast机制
HashMap不是线程安全的集合类
modCount为HashMap的一个实例变量,并且被声明为volatile,表示任何线程都可以看到该变量被其它线程修改的结果(根据JVM内存模型的优化,每一个线程都会存一份自己的工作内存,此工作内存的内容与本地内存并非时时刻刻都同步,因此可能会出现线程间的修改不可见的问题) 。使用Iterator开始迭代时,会将modCount的赋值给expectedModCount,在迭代过程中,通过每次比较两者是否相等来判断HashMap是否在内部或被其它线程修改。HashMap的大多数修改方法都会改变ModCount。put、remove、clear方法都改变modCount的值。
通过检查状态——没有问题则忽略——有问题则抛出异常的方式,来避免线程同步的开销。

4.并发
在通常并发环境下,还是建议采用同步机制。这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止意外的非同步访问。

LinkedHashMap:

1.前者维护着一个运行于所有条目的双重链接列表,此链接列表定义了迭代顺序,该迭代顺序通常就是集合中元素的插入顺序。该类定义了header、before与after三个属性来表示该集合类的头与前后“指针”,其具体用法类似于数据结构中的双链表。由于增加了维护链接列表的开支,其性能要比 HashMap 稍逊一筹。
LinkedHashMap的迭代所需时间与其的所包含的元素成比例;而HashMap 迭代时间很可能开支较大,因为它所需要的时间与其容量(分配给Key空间的长度)成比例。一言以蔽之,随机存取用HashMap,顺序存取或是遍历用LinkedHashMap。
2.LinkedHashMap还重写了removeEldestEntry方法以实现自动清除过期数据的功能,这在HashMap中是无法实现的,因为后者其内部的元素是无序的。缺省情况下,LinkedHashMap采取的更新策略是类似于队列的FIFO。

1 0