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
效率差10HashMap扩容,
当前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&lt;String,Object&gt;的某个值排序

HDU 1247 Hat’s Words (字典树 &amp;&amp; map)

ConcurrentHashMap & Hashtable

map&reduce

并发库应用之十二 & 同步集合类的应用