Java中Hashtable、HashMap、TreeMap的比较
大家好,我是joker,希望你快乐。
最常见的Map实现,以键值对的形式存储和操作的数据容器。
Hashtable
Hashtable是同步的,不支持null键和值
HashMap
HashMap不是同步的,支持null键和值,内部数据结构为数组+链表组成的复合结构,如果链表的大小超过阈值(TREEIFY_THRESHOLD,8)就会被改造为树形结构。resize()方法负责初始化和扩容。putVal()方法包括很多逻辑如初始化,扩容,树化。阈值=负载因子*容量。以倍数调整容量及阈值。扩容后需要将老数组中的元素放到新数组中。
树化:当链表的长度超过阈值TREEIFY_THRESHOLD
如果总容量小于MIN_TREEIFY_CAPACITY,扩容
如果总容量大于MIN_TREEIFY_CAPACITY,树化
TreeMap
TreeMap不是同步的,基于红黑树的一种提供顺序访问的Map,具体顺序由Comparator或Comparable决定。
LinkedHashMap提供按插入顺序的遍历访问,通过维护一个双向链表
HashMap中的put,get方法分析
JDK1.8 HashMap
put方法操作
0.putVal方法获取hash值,调用hashcode方法,然后用获取到的hash值与自身高16位进行异或运算
1.先判断是否初始化过,如果没有初始化,调用resize方法进行初始化
2.用哈希值和数组长度-1进行与运算获取索引值,判断该位置是否已经存放Node,如果没有,创建Node存入
3.如果索引位置已经存放Node,判断key是否存在,如果存在,覆盖value值,返回旧值
4.如果key不存在,判断Node是否为TreeNode,如果是TreeNode,把Node转为TreeNode,存入红黑树中
5.如果不为树,则为链表,遍历链表,如果key存在,覆盖值,直到链表最后一个Node,创建新节点加入,如果链表个数大于8进行树化
6.treeifyBin树化内部判断数组是不是太小,如果太小不树化,先扩容
7.resize扩容,2倍扩容,扩容后数据移动,因为2倍扩容,数组长度-1求hash,所以元素会在原始位置或原始位置加数组原始长度
8.扩容元数据移动链表元素会在原始位置或原始位置加数组原始长度,树也是分高低位,根据节点数据量判断是否树化还是退化到链表
get方法操作
0.先判断容器中是否有元素,首节点是否有元素,没有直接返回null
1.如果有判断首节点key是否相等,相等返回首节点
2.如果首节点key不相等,判断后面是否有元素,没有直接返回null
3.如果有元素判断是树还是链表,查找,找到返回对应元素,未找到返回null
HashMap 1.7 1.8区别:1.7采用数组+链表,1.8采用数组+链表/红黑树,1.7采用头插法,1.8采用尾插法
来源:http://www.cnblogs.com/Crazy_Joker
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。