HashMap相关总结

HashMap作为java常用集合类之一,也是面试必考的题目之一,在此做一期hashmap相关的知识点总结。

一、hashMap原理

一问到hashMap原理,应该能说出它是基于数组与链表结构。当put一组键值对时,会以key为参数,获取到一个hash值,这个值用于在数组里找脚标,找到后获取该脚标下的元素,如果为空,则新建。不为空,则以链表形式存储上。同样的,当使用get方法时,仍然要通过key获取到hash值,再以这个值作为脚标去获取数组中的元素。值得一提的是,获取的元素是链表头部,还需以key作为对比遍历链表,如果匹配上,则取出对应value,如果没有,返回空。

二、hashTable与hashMap的区别

二者都实现了map接口,但是hashmap继承了AbstractMap而hashtable继承了Dictionary。从源码中可以看到,hashtable中的大部分方法都加了synchronized关键字,确保了方法调用时的线程同步。

HashMap可以通过下面的语句进行同步: 

Map m = Collections.synchronizeMap(hashMap); 

Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。

三、ConcurrentHashMap

ConcurrentHashMap的数据结构是由一个Segment数组和多个HashEntry组成。

Segment数组的意义就是将一个大的table分割成多个小的table来进行加锁,Segment数组中每一个元素就是一把锁,每一个Segment元素存储的是HashEntry数组+链表,这个和HashMap的数据存储结构一样。 

默认ConcurrentHashMap长度是16。

HashTable容器的get方法是需要加锁的,那么ConcurrentHashMap的get操作是如何做到不加锁的呢?原因是它的get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。

经常说到hashtable和hashmap的区别的时候都会说:hashtable是线程安全的,hashmap是非线程安全的,但是说hashtable是线程安全的其实也是不太准确的,因为hashtable在复合操作下也是非线程安全的,而Concurrenthashmap对于复合操作仍然是线程安全的。

关于ConcurrentHashMap,请参考聊聊ConcurrentHashMap

四、LinkedHashMap

LinkedHashMap继承于hashMap,相比于hashMap,它多了head和tail等变量,用于控制顺序。LinkedHashMap保存记录了插入顺序,在用Iterator遍历LinkedHashMap时、先得到的记录肯定是先插入的.也可以在构造时用带参数、按照应用次数排序、在遍历的时候会比HashMap慢、不过有种情况例外、当HashMap容量很大、实际数据较少时、遍历起来可能会比LinkedHashMap慢、因为LinkedHashMap的遍历速度只和实际数据有关、和容量无关、而HashMap的遍历速度和他的容量有关

五、TreeMap

TreeMap实现SortMap接口、能够把它保存的记录根据键排序,默认是按键值的升序排序、也可以指定排序的比较器、当用Iterator 遍历TreeMap时、得到的记录是排过序的


总结下来还是hashmap比较经典,同时也是使用最多的,至于线程同步要求下,还是使用ConcurrentHashMap。其它几个都不太常用。


猜你喜欢

转载自blog.csdn.net/Kongou/article/details/80791507