HashMap&ConcurrentHashMap

基本的位操作

  • 与( & )每一位进行比较,两位都为1,结果为1,否则为0(-4 & 1 = 0)
  1 0 0 1 1 -->(19)[10] 表示10进制中的19

& 1 1 0 0 1 -->(25)[10]

  1 0 0 0 1 -->(17)[10]
  • 或( | )每一位进行比较,两位有一位是1,结果就是1(-4 | 1 = -3)
  1 0 0 1 1 -->(19)[10]
| 1 1 0 0 1 -->(25)[10]
------------------------------
  1 1 0 1 1 -->(27)[10]
  • 非( ~ ) 每一位进行比较,按位取反(符号位也要取反)(~ -4 = 3)
~ 1 0 0 1 1 -->(19)[10]
-----------------------------
  0 1 1 0 0 -->(12)[10]
  • 异或( ^ )每一位进行比较,相同为0,不同为1(^ -4 = -3)
  1 0 0 1 1 -->(19)[10]
^ 1 1 0 0 1 -->(25)[10]
-----------------------------
  0 1 0 1 0 -->(10)[10]
  • 左移( << ) 整体左移,右边空出位补零,左边位舍弃 (-4 << 1 = -8)
int a = 8;
a << 3;
移位前:0000 0000 0000 0000 0000 0000 0000 1000 -->(8)[10]
移位后:0000 0000 0000 0000 0000 0000 0100 0000 -->(64)[10]  相当于 X 2^3
  • 右移( >> ) 整体右移,左边空出位补零或补1(负数补1,整数补0),右边位舍弃 (-4 >> 1 = -2)
unsigned int a = 8;
a >> 3;
移位前:0000 0000 0000 0000 0000 0000 0000 1000 -->(8)[10]
移位后:0000 0000 0000 0000 0000 0000 0000 0001 -->(1)[10] 相当于 / 2^3int a = -8;
a >> 3;
移位前:1111 1111 1111 1111 1111 1111 1111 1000 -->(-8)[10]
移位前:1111 1111 1111 1111 1111 1111 1111 1111 -->(-1)[10] 
  • 无符号右移( >>> )同>>,但不管正数还是负数都左边位都补0 (-4 >>> 1 = 2147483646)

HashMap

构造方法中初始容量计算

static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

初始容量不大于最大容量的情况下,返回大于输入参数且最接近2的整数次幂的数。比如输入10,返回16。
在这里插入图片描述
多次右移、或位运算后将n低位全置为1,返回n+1就为1个1后面全为0(10000),n+1用10进制就是2的整数次幂。
cap - 1:处理参数为2的整数次幂的情况。

ConcurrentHashMap

ConcurrentHashMap1.7使用分段锁;1.8使用 CAS+synchronized实现并发安全。
HashMap1.8扩容多线程会创建多个hashtable,ConcurrentHashMap1.8多线程会帮忙一起扩容。

final V putVal(K key, V value, boolean onlyIfAbsent) {
	if (key == null || value == null) throw new NullPointerException();
	int hash = spread(key.hashCode());
	int binCount = 0;
	for (Node<K,V>[] tab = table;;) {//多线程CAS算法
	    Node<K,V> f; int n, i, fh;
	    if (tab == null || (n = tab.length) == 0)
	        tab = initTable();
	    //table下标所在值为空,使用CAS将value插入,多线程时,其他线程会CAS插入失败,经过for循环走到下面if判断 
	    else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
	        if (casTabAt(tab, i, null,
	                     new Node<K,V>(hash, key, value, null)))
	            break;                   // no lock when adding to empty bin
	    }
	    //扩容时将节点置为ForwardingNode,此时hash为-1,等于MOVED
	    //另一个线程正在扩容,会帮忙扩容
	    else if ((fh = f.hash) == MOVED)
	        tab = helpTransfer(tab, f);
	    else {
	        V oldVal = null;
	        //table下标所在值不为空,使用synchronized在f上加锁,插入链表,锁的是Bucket(链表/红黑树) 
	        synchronized (f) {
	            if (tabAt(tab, i) == f) {
	                if (fh >= 0) {
	                    binCount = 1;
	                    for (Node<K,V> e = f;; ++binCount) {
	                        K ek;
	                        if (e.hash == hash &&
	                            ((ek = e.key) == key ||
	                             (ek != null && key.equals(ek)))) {
	                            oldVal = e.val;
	                            if (!onlyIfAbsent)
	                                e.val = value;
	                            break;
	                        }
	                        Node<K,V> pred = e;
	                        if ((e = e.next) == null) {
	                            pred.next = new Node<K,V>(hash, key,
	                                                      value, null);
	                            break;
	                        }
	                    }
	                }
	                else if (f instanceof TreeBin) {
	                    Node<K,V> p;
	                    binCount = 2;
	                    if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
	                                                   value)) != null) {
	                        oldVal = p.val;
	                        if (!onlyIfAbsent)
	                            p.val = value;
	                    }
	                }
	            }
	        }
	        if (binCount != 0) {
	            if (binCount >= TREEIFY_THRESHOLD)
	                treeifyBin(tab, i);
	            if (oldVal != null)
	                return oldVal;
	            break;
	        }
	    }
	}
	addCount(1L, binCount);
	return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值