hashmap的底层

HashMap是无序的,底层是哈希表(数组+单向链表+红黑树)
LinkedHashMap是有序的; 数组+双向链表
所以,当我们需要存储的元素有序拿出,那就使用LinkedHashMap。

但是,以上两个都是线程不安全的,想使用安全的map集合可以用juc包下的concurrentMap或者Collections下的synchronizedMap

哈希表 在jdk8前是数组+链表 ,jdk8后市数组+链表+红黑树
HashMap 有加载因子0.75,默认长度为16,自动桶数(数组大小)一倍扩容(超过12扩容,小于8恢复)
链表长度大于8从链表变成红黑树,小于6就是冲红黑树变成链表。

细说hashmap的底层

哈希表 = 数组 + 链表 + 红黑树

问题:为什么jdk8后又添加了红黑树呢?
答:因为,链表是按照顺序存储的,但是红黑树是按照值去存储的树状结构。
当桶内数据越来越多时,链表的查询效率显然就弱了,所以在超过一定存储数量之后,桶内的存储结构就从链表替换为了红黑树.默认是当大于8个元素时会转为红黑树

首先,明白几个概念:

  • 链表相当于node节点(由头部和地址组成;暴露头部,隐藏引用地址)数组
  • 默认数组大小为16,表示有16个桶bucket
  • 链表)或者红黑树是存储在数组每个元数(桶)中,开始是默认长度为8的链表,超过8变成红黑树,小于6 又回到链表

存储和取出数据

  • 数据存储:把key求取hash值,拿着这个hash值去找桶,找到桶后,存储在链表或者红黑树中

  • 数据取出:也是通过key的hash值去找到对应的桶,然后判断桶是链表还是红黑树,链表就遍历查找,红黑树TODO查找

这里杠精可能会说又对象不一样,但是hash值相等的情况,如何解决呢?请看下面

就拿取出数据来说:
  (1) 获得key的hashcode,通过hash()散列算法得到hash值,进而定位到数组的位置(哪一个桶)。
  (2) 在链表上挨个比较key对象。 调用equals()方法(解决了上诉的问题),将key对象和链表上所有节点的key对象进行比较,直到碰到返回true的节点对象为止。
  (3) 返回equals()为true的节点对象的value对象。

同理可以反推存储过程。

hashmap源码

//桶数量的默认值(16),而不是桶内可以装的元素的数量
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
 
//必须为2的n次方,所以最大为2^30
static final int MAXIMUM_CAPACITY = 1 << 30;
/*
    默认负载系数为0.75,当表中超过75%的位置已经填入元素,这个表就会用双倍的桶数自动地进行
    再散列(rehashed),可以通过构造函数初始化
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
 
//桶内数据量超过这个阈值就会将桶内数据结构从链表转为红黑树
static final int TREEIFY_THRESHOLD = 8;
 
//当小于这个数值时将红黑树转为链表
static final int UNTREEIFY_THRESHOLD = 6;
 
//在第一次使用时初始化Node数组,桶对象数组
transient Node<K,V>[] table;
 
//该HashMap中共有多少个键值对
transient int size;
 
//桶的数量,默认为DEFAULT_INITIAL_CAPACITY,即16
int threshold;

分析:

  • 1 << 4;表示左移,就是移动2的多少次幂,1 * 2^4= 16
  • table就是桶,是一个node数组,那就表示可以存储链表和红黑树
  • threshold 是桶的个数,也就是数组的大小,为16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LC超人在良家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值