Collections&Map&Set&List
Posted PoetryAndTheDistance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Collections&Map&Set&List相关的知识,希望对你有一定的参考价值。
HashMap
1.7-hashtable = 数组(基础) + 链表
(>=)1.8 = 数组 + 链表 + 红黑树
HashMap->数组的大小
new HashMap();如果不写构造参数,默认大小16
如果说:写了初始容量:11 ?hashmap的容量就是11?
hashmap的get,put操作时间复杂度O(1)
key.hashCode = 不确定 - 有符号的整型值
key.hashCode % 16 = table.lenth = [0-15] = index = 3;
array[index] = value;
数组所有的元素位是否能够100%被利用起来?
不一定,hash碰
引入链表结构解决hash冲突,采用头部插入链表法,链表时间复杂度O(n)
hash并不是用取模计算index,而是用位运算!
效率:位运算>%
并没有说hashmap的容量一定是16,
/** * The default initial capacity - MUST be a power of two. */必须是2的指数幂?
roundUpToPowerOf2(size),强型将非2的指数次幂的数值转化成2的指数次幂
怎么转化?
1、必须最接近size,11
2、必须大于=size,
3、是2的指数次幂
16
size = 17,capacity = 32
为什么一定要转成2的指数次幂?
计算索引:int i = indexFor(hash, table.length);
static int indexFor(int h, int length) {
// key.hashCode % table.lenth
return h & (table.lenth-1);
}
h =
0001 0101 0111 0010 1111
0001 0101 0000 0010 0000
16
0
0000 0000 0000 0000 1111 16-1=15
0000 0000 0000 0000 1010
0-15
bit位运算:1815ms
mod取模运算:22282
效率差10倍
HashMap扩容,
当前hashmap存了多少element,size>=threshold
threshold扩容阈值 = capacity * 扩容阈值比率 0.75 = 16*0.75=12
扩容怎么扩?
扩容为原来的2倍。
转移数据
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);//再一次进行hash计算?
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
链表成环,死锁问题
hash扩容,有个加载因子?loadfactor = 0.75为什么是0.75
0.5
1
牛顿二项式:基于空间与时间的折中考虑0.5
引入红黑树!
容量>=64才会链表转红黑树,否则优先扩容
只有等链表过长,阈值设置TREEIFY_THRESHOLD = 8,不是代表链表长度,链表长度>8,链表9的时候转红黑树
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
//yangguo.hashcode & 16 = 0,用低位指针
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
//yangguo.hashcode & 16 》 0 高位指针
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;,移到新的数组上的同样的index位置
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead; //index 3+16 = 19
}
完全绕开rehash,要满足高低位移动,必须数组容量是2的幂次方
分库分表,在线扩容
2台master tuling(1,2,3,4) -> 4台
以上是关于Collections&Map&Set&List的主要内容,如果未能解决你的问题,请参考以下文章
迭代器遍历ListSetMap&& 遍历集合的方法总结 && Collections工具类
list中依据map<String,Object>的某个值排序