子类HashMap:
基于Hash表实现的一个Map结构(k-v键值对)
1、jdk1.2提供的,线程不安全的
2、初始化的数组长度是16,是2的幂次方
3、jdk8之后,如果链表的长度大于8,这个单向链表就会转换为红黑树
如果链表长度小于6位,就会从红黑树转换链表
4、数组扩容时,扩容的大小是原有数组长度的的2倍。
5、HashMap的键可以是null,但是只能有一个
子类Hashtable:
1、jdk1.0提供的,线程安全的,
2、初始化的数组长度是11
3、Hashtable的键不能为空
4、数组扩容时,扩容的大小是原有数组长度的的2倍 + 1。
java.uti.concurrent juc包
ConcurrentHashMap:
jdk1.5提供的包中的类
也是线程安全的,bucket(桶),对每一个桶加锁,也就是意味着
ConcurrentHashMap虽然是线程安全的,但是效率默认就是Hashtable 16倍
包含的contains方法不同
1.HashMap是没有contains方法的,而包括containsValue和containsKey方法。
2.hashtable则保留了contains方法,效果同containsValue,还包括containsValue和containsKey方法。
3.concurrenthashmap也是没有contains方法的,而包括containsValue和containsKey方法。
计算hash值方式不同
②:Hashtable通过计算key的hashCode()**来得到hash值就为最终hash值。
-
为了得到元素的位置,首先需要根据元素的 KEY计算出一个hash值,然后再用这个hash值来计算得到最终的位置。
①:HashMap有个hash方法重新计算了key的hash值,因为hash冲突变高,所以通过一种方法重算hash值的方法。 -
先调用hashCode方法计算出来一个hash值,再将hash与右移16位后相异或,从而得到新的hash值。
-
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
-
它们计算索引位置方法不同:
HashMap在求hash值对应的位置索引时,index = (n - 1) & hash。将哈希表的大小固定为了2的幂,因为是取模得到索引值,故这样取模时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。 -
HashTable在求hash值位置索引时计算index的方法
-
int index = (hash & 0x7FFFFFFF) % tab.length;
&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号位改变,而后面的位都不变。