Hashmap其实是一个数组和链表的结合体,利用数组来模拟一个个桶(相似于Bucket Sort)以快速存取不一样hashCode的key,对于相同hashCode的不一样key,再调用其equals方法从List中提取出和key所相对应的value。数组存储的是链表,链表是为了解决哈希冲突的。 java
每当hashMap扩容后,内部的每一个元素存放的位置都会发生变化(由于元素的最终位置是其hashCode对key空间长度取模而得),所以resize方法中又会调用transfer函数,用来从新分配内部的元素;这个过程成为rehash,是十分消耗性能的,所以在可预知元素的个数的状况下,通常应该避免使用缺省的initialCapacity,而是经过构造函数为其指定一个值。例如咱们可能会想要将数据库查询所得1000条记录以某个特定字段(好比ID)为key缓存在hashMap中,为了提升效率、避免rehash,能够直接指定initialCapacity为2048。
Fail-Fast机制:咱们知道java.util.HashMap不是线程安全的,所以若是在使用迭代器的过程当中有其余线程修改了map,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。 数据库
这一策略在源码中的实现是经过modCount域,modCount顾名思义就是修改次数,对HashMap内容的修改都将增长这个值,那么在迭代器初始化过程当中会将这个值赋给迭代器的expectedModCount。 数组
LinkedHashMap的实现与 HashMap 的不一样之处在于,前者维护着一个运行于全部条目的双重连接列表,增长了维护连接列表的开支,其性能要比 HashMap 稍逊一筹,不过有一点例外:LinkedHashMap的迭代所需时间与其的所包含的元素成比例;而HashMap 迭代时间极可能开支较大,由于它所须要的时间与其容量(分配给Key空间的长度)成比例。一言以蔽之,随机存取用HashMap,顺序存取或是遍历用LinkedHashMap。 缓存
这种数据结构很适合构建 LRU 缓存。缺省状况下,LinkedHashMap采起的更新策略是相似于队列的FIFO,若是你想实现更复杂的更新逻辑好比LRU(最近最少使用)。 安全
JAVA中确实存在着与其密切相关的四种引用:强引用、软引用、弱引用以及幻象引用。 数据结构
HashMap采用的是采用相似于强引用的强键来管理的,这意味着即便做为key的对象已经不存在了(指没有任何一个引用指向它),也仍然会保留在HashMap中,在某些状况下(例如内存缓存)中,这些过时的条目可能会形成内存泄漏等问题。 函数
WeakHashMap弱引用特别适合如下对象:占用大量内存,但经过垃圾回收功能回收之后很容易从新建立 性能
介于HashMap和WeakHashMap之中的是SoftHashMap,它所采用的软引用的策略指的是,垃圾收集器并不像其收集弱可及的对象同样尽可能地收集软可及的对象,相反,它只在真正 “须要” 内存时才收集软可及的对象。软引用对于垃圾收集器来讲是一种“睁一只眼,闭一只眼”方式。 spa
其实要比WeakHashMap更适合于实现缓存机制。遗憾的是,JAVA中并无实现相关的SoftHashMap类(Apache和Google提供了第三方的实现)