HashMap、Hash Table、ConcurrentHashMap

This this. . . Since the king has recently started to look for internships, so the cow brush off some of the Internet companies face questions, most of them are some java, front-end HTML, js, jquery, as well as a number of algorithms for a long time did not touch the question, to be honest, a bit uncomfortable , in fact, I do not know a lot of local knowledge and many loopholes like this one to write this, it is when I brush my question really feel vacant place, and why? Because, do more, much more wrong. However, it is embarrassing is that just because a lot of companies also face questions, so simply write down the finishing straight again.

Here I would also suggest that cattle off network is not just a job search station is a place where we can exercise, nothing brush that ah, ah stroll forum, maybe you can find a lot of unexpected things.

During the interview, there are several problems are more common.

  1. HashTable, HashMap, ConcurrentHashMap difference?
  2. Scene HashMap thread appears unsafe?
  3. When HashMap put data storage method is how to determine whether repeated?   
  4. JDK7 and JDK8  implementation of HashMap What is the difference?
  5. Why HashMap length is a power of 2?

After just put a few questions over again, a general understanding of the differences between each other and their respective roles again! ! In fact, it can knock again mastered.

HashTable

  • + Linked list to achieve the underlying array, whether key or value can not be null , thread- safe , thread-safe way to achieve lock the entire HashTable when data is modified, low efficiency, ConcurrentHashMap do the relevant optimization
  • The initial size of 11 , expansion: newsize = oldsize * 2 + 1
  • The method of calculating the index: index = (hash & 0x7FFFFFFF)% tab.length

HashMap

  • + Underlying array implemented in the list, thread-safe, and may store a null key null value
  • The initial size of 16, can be expanded: newsize = oldsize * 2, size of certain n-th power of 2
  • Expansion for the entire Map, a time when the expansion of the original elements in the array in order to recalculate the storage position, and reinsert
  • Should the judge after the expansion element is inserted, there may not be valid expansion (if inserted expansion, if not insert it again, it will generate invalid expansion)
  • Map when the total number of elements exceeds 75% Entry array, triggering expansion operation, in order to reduce the length of the list, a more uniform distribution element
  • The method of calculating index: index = hash & (tab.length - 1)

* The initial value of the load factor of the HashMap also consider:
hash collision: Key after several hash value by modulo array size, if the array falls on the same subscript, the composition of an Entry chain, to find the need to traverse Key each element on the chain execution Entry equals () comparison.
Load factor: In order to reduce the probability of hash collision, the default when the HashMap of key-value pairs reaches 75% of the size of the array that will trigger expansion. Thus, if the estimated capacity of 100, i.e., the need to set 100 / 0.75 = 134 is the size of the array.
Space for time: if you want to speed up the time Key probability to find, can further reduce the load factor, increase the initial size to reduce hash conflicts.

HashMap and distinction of HashTable (~ interview questions often test)

1. The difference between the two parent class inherits

HashMap class is inherited from AbstractMap, and HashTable is inherited from the Dictionary class. But they have achieved while achieving the map, Cloneable (can be copied), Serializable (serializable) three interfaces.

Here originally intercepted inside the JDK API1.6 Chinese version, but it is ugly, it is in someone else's blog, Oh, quiet Mimi took over what draws

 2. Both external interface is different

Providing HashTable elements () and contains () method than two multi HashMap.

elements () method inherited from the parent class Doctionnary the HashTable. elements () method returns the enumerated value HashTable case.

contains () method determines whether the Hashtable contains incoming value. Its role () is consistent with containsValue. In fact, contansValue () just calls it contains () method, is to determine whether the hash table contains the specified value. FIG source is contains:

public virtual bool Contains(object key)
{
    return this.ContainsKey(key);
}

3. Null key support different and Null value of
Hashtable neither supports nor Null key support Null value.

The HashMap, key-value are present in the Entry. as null key, only one such bond; can have one or more keys corresponding to the null value, the order of elements does not guarantee constancy, its underlying using arrays and lists, used HashCode () method and equal () method to guarantee the uniqueness of the key. When the get () method returns a null value, this may not be a HashMap key, also possible for the key corresponding to the value of null. Thus, in a HashMap can not get () method to determine whether there is a key HashMap rather should containsKey () method to determine.
4. Different thread safe sex

Hashtable is thread-safe, it's each method are added to the Synchronize method. In multi-threaded environment, you can directly use the Hashtable, synchronization is not necessary for it to achieve their own way.

HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。所以使用HashMap时就必须要自己增加同步处理,

虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。
5.Hash值的计算方法不同

为了求得元素的位置,需要根据元素的Key计算出一个哈希值,然后再用这个哈希值来计算出崔忠的位置。

Hashtable直接使用对象的hashCode。hashCode是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值。然后再使用除留余数发来获得最终的位置。

Hashtable在计算元素的位置时需要进行一次除法运算,而除法运算是比较耗时的。

HashMap为了提高计算效率,将哈希表的大小固定为了2的幂,这样在取模预算时,不需要做除法,只需要做位运算。位运算比除法的效率要高很多。

HashMap的效率虽然提高了,但是hash冲突却也增加了。因为它得出的hash值的低位相同的概率比较高,而计算位运算

为了解决这个问题,HashMap重新根据hashcode计算hash值后,又对hash值做了一些运算来打散数据。使得取得的位置更加分散,从而减少了hash冲突。当然了,为了高效,HashMap只做了一些简单的位处理。从而不至于把使用2 的幂次方带来的效率提升给抵消掉。

ConcurrentHashMap

  • 底层采用分段的数组+链表实现,线程安全。
  • key和value都不能为null。
  • 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。
  • Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
  • 有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁
  • 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

这个就很棒了,上面总结的源于某猿大神,Java5提供的ConcurrentHashMap就像是HashTable的升级版,扩容性更强。

在HashMap中,通过get()返回的null值,既可以表示返回该Key所对应过的Value是null值,也可以表示为没有该Key,在这种情况下就应该采用ConcurrentHashMap。

来看一张简单的类图:

ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一个可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组。Segment的结构和HashMap类似,是一种数组和链表结构。一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment守护着一个HashEntry数组里的元素。当对HashEntry数组的数据进行修改时,必须首先获得与它对应的segment锁。

 Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

简单理解就是,ConcurrentHashMap是一个Segment数组,Segment通过继承ReentrantLock来进行加锁,所以每次需要加锁的操作锁住的是一个Segment,只要保证每个Segment是线程安全的,也就实现了全局的线程安全。重申一下,Segment数组不能扩容,扩容是Segment数组某个位置内部的数组HashEntry<K,V>[]进行扩容,扩容后,容量为原来的2倍。可以回顾下出发扩容的地方,put的时候,如果判断该值的插入会导致该Segment的元素个数超过阈值,那么先进行扩容,再插值。

Guess you like

Origin www.cnblogs.com/wudidamowang666/p/11286279.html