看完脑图,个中很多还是不足详细的。只是概述了内容。HashMaphashMap的概述
hashMap,继续Map凑集,以key-value形式存储,个中key可以为null ,value是可以重复,其数据是无序的,且会在扩容的时候发生改变。
hashMap在进行存储的时候的步骤链表转红黑树在1.8的时候,hashMap加用了红黑树的数据构造,当某一数组的某一个位置hash冲突达到8个的时候,就会将链表转为红黑树,其缘故原由便是提高插入和查找的效率,利用链表的插入尾节点的效率是o(n),而利用了红黑树的话插入和查找都是O(logn)我们来看一下详细的插入流程:
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }1234
1.7 的打算办法将打算出来的hash值和数组的长度减1进行与运算,打算出来
static int indexfor(int h,int length) {// 个中的legth-1 也是为什么 hashMap的容量为2的n次幂的缘故原由return h & (length-1);}1234
从上面的两种通过hash值打算数组下表位置index的办法都可以将打算出来的值在数组length的长度内。至于那种性能更高速率更快,散列的空间更加均匀,那毋庸置疑,肯定1.8里面的。
上面说到可负载因子是0.75,为什么默认的负载因子是0.75呢?个人理解:首先0.75 会用作扩容,这个值越大直到1,那扩容的次数是不是概率越低,hash冲突是不是越小?由于他这个值决定了达到多大值就会扩容。如果设置一个0.1,那么在第一次存储完成后就扩容了,那肯定第二次进行打算hash的时候由于数组很大,那也就降落了hash碰撞。我的理解便是在扩容次数和hash冲突之间起到一个平衡的浸染jdk1.7 中的注讲授明:作为一样平常规则,默认负载因子(0.75)在韶光和空间本钱上供应了很好的折衷。较高的值会降落空间开销,但提高查找本钱(表示在大多数的HashMap类的操作,包括get和put)。设置初始大小时,该当考虑估量的entry数在map及其负载系数,并且只管即便减少rehash操作的次数。如果初始容量大于最大条款数除以负载因子,rehash操作将不会发生。jdk 1.8中 :空想状态下,在随机哈希值的情形,对付loadfactor = 0.75 ,虽然由于粒度调度会产生较大的方差,桶中的Node的分布频率服从参数为0.5的泊疏松布。hash冲突的几种办理办法开放定址法从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元。然后把发生冲突的元素存入到该单元的一种方法。链地址法(拉链法)hashMa也便是用的这种办法链接地址法的思路是将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除紧张在同义词链表中进行。链表法适用于常常进行插入和删除的情形。再哈希法便是同时布局多个不同的哈希函数:Hi = RHi(key) i= 1,2,3 … k;当H1 = RH1(key) 发生冲突时,再用H2 = RH2(key) 进行打算,直到冲突不再产生,这种方法不易产生聚拢,但是增加了打算韶光。既然已经看了hashMap的源码我们再联系一下线程安全的hashMap都有哪些呢ConcurrentHashMap不用说我们都知道concurrentHahMap是线程安全版的hashmap ,其底层源码与hashMap类似,但是在数据构造上改变了一下,加了一个sagment[] ,这个sagement工具数组里面有多个小的hashMap,在进行操作的时候会对sagment进行加锁,让其同步实行。由于当sagment里面hashMap越多的时候那么这个并发安全系数就越低,以是在ConcurrentHashMap里面有一个并发安全系数。来掌握sagment里面的hashMap的数量。其上面的说法是jdk1.7版本,这个锁采取的是rentrantLock。但是在JDK1.8中利用的是更细粒度的锁利用Sychronized和CAS来进行枷锁。1.8中的一个列子1.7中的sagement[]//get方法是不加锁的,所有共享变量都是通过volatile润色的,确保或许最新值public V get(Object key) { Segment<K,V> s; HashEntry<K,V>[] tab; int h = hash(key); long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE; if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null && //获取volatile (tab = s.table) != null) { for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile //获取volatile (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE); e != null; e = e.next) { K k; if ((k = e.key) == key || (e.hash == h && key.equals(k))) return e.value; } } return null; }1234567891011121314151617
HashTableHashTable也是hashMap的线程安全版本,由于自身性能的问题,也一贯没有被优化,以是其版本一贯没改变。HashTable是给其各个方法加了sychronized关键字所有的实行都会同步实行。hashTable慢的相对付ConcurrentHashMap来说。