也許你並不知道的HashMap和HashTable區別

背景

也許你並不知道的HashMap和HashTable區別

面試官:說一下HashMap和Hashtable的區別吧?
面試者:1. HashMap是線程非安全的,Hashtable是線程安全的
2.HashMap比HashTable快
3.Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴展性更好。
面試官:HashMap是否支持null Key,null value?HashTable是否支持null Key,null value?
面試者:HashMap支持null key和null value,HashTable也支持null key和null value
面試官:爲何?
面試者:規定的
面試者心裏:崩潰!我也不知道爲何!上面都是面試題背的。
面試官:回去等通知吧面試

上面的面試場景你是否經歷過?這個問題也許會傷到不少面試者的心,那咱們扒出來這兩個的源碼來細細看看!安全

HashMap爲何支持null鍵值?

1.咱們知道HashMap的能夠要作Hash處理的過程:app

/**
 * Computes key.hashCode() and spreads (XORs) higher bits of hash
 * to lower. Because the table uses power-of-two masking, sets of
 * hashes that vary only in bits above the current mask will
 * always collide. (Among known examples are sets of Float keys
 * holding consecutive whole numbers in small tables.) So we
 * apply a transform that spreads the impact of higher bits
 * downward. There is a tradeoff between speed, utility, and
 * quality of bit-spreading. Because many common sets of hashes
 * are already reasonably distributed (so don't benefit from
 * spreading), and because we use trees to handle large sets of
 * collisions in bins, we just XOR some shifted bits in the
 * cheapest possible way to reduce systematic lossage, as well as
 * to incorporate impact of the highest bits that would otherwise
 * never be used in index calculations because of table bounds.
 */
 static final int hash(Object key) {
 int h;
 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
 }

當key爲null時,將key的值置爲0計算ide

2.Hashcodethis

值得分佈狀況:線程

public final int hashCode() {
 return Objects.hashCode(key) ^ Objects.hashCode(value);
 }
/**
 * Returns the hash code of a non-{@code null} argument and 0 for
 * a {@code null} argument.
 *
 * @param o an object
 * @return the hash code of a non-{@code null} argument and 0 for
 * a {@code null} argument
 * @see Object#hashCode
 */
 public static int hashCode(Object o) {
 return o != null ? o.hashCode() : 0;
 }

當value爲null時,默認爲0設計

HashTable爲何不支持null鍵值

1.key不能爲null,不然報空指針異常指針

/**
 * Tests if some key maps into the specified value in this hashtable.
 * This operation is more expensive than the {@link #containsKey
 * containsKey} method.
 *
 * <p>Note that this method is identical in functionality to
 * {@link #containsValue containsValue}, (which is part of the
 * {@link Map} interface in the collections framework).
 *
 * @param value a value to search for
 * @return <code>true</code> if and only if some key maps to the
 * <code>value</code> argument in this hashtable as
 * determined by the <tt>equals</tt> method;
 * <code>false</code> otherwise.
 * @exception NullPointerException if the value is <code>null</code>
 */
 public synchronized boolean contains(Object value) {
 if (value == null) {
 throw new NullPointerException();
 }

 Entry<?,?> tab[] = table;
 for (int i = tab.length ; i-- > 0 ;) {
 for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
 if (e.value.equals(value)) {
 return true;
 }
 }
 }
 return false;
 }

2.value不能爲null,不然報空指針異常code

/**
 * Maps the specified <code>key</code> to the specified
 * <code>value</code> in this hashtable. Neither the key nor the
 * value can be <code>null</code>. <p>
 *
 * The value can be retrieved by calling the <code>get</code> method
 * with a key that is equal to the original key.
 *
 * @param key the hashtable key
 * @param value the value
 * @return the previous value of the specified key in this hashtable,
 * or <code>null</code> if it did not have one
 * @exception NullPointerException if the key or value is
 * <code>null</code>
 * @see Object#equals(Object)
 * @see #get(Object)
 */
 public synchronized V put(K key, V value) {
 // Make sure the value is not null
 if (value == null) {
 throw new NullPointerException();
 }

 // Makes sure the key is not already in the hashtable.
 Entry<?,?> tab[] = table;
 int hash = key.hashCode();
 int index = (hash & 0x7FFFFFFF) % tab.length;
 @SuppressWarnings("unchecked")
 Entry<K,V> entry = (Entry<K,V>)tab[index];
 for(; entry != null ; entry = entry.next) {
 if ((entry.hash == hash) && entry.key.equals(key)) {
 V old = entry.value;
 entry.value = value;
 return old;
 }
 }

 addEntry(hash, key, value, index);
 return null;
 }

jdk 爲何這麼設計?orm

jdk的設計爲何沒有保持一致?

首先,咱們看一下HashTable

/ * @author Arthur van Hoff

  • @author Josh Bloch
  • @author Neal Gafter
  • @since JDK1.0
    */
    它是jdk1.0的第一個版本出現的,主要設計者是Arthur van Hoff,也許設計者當時認爲null做爲key 和value 是沒有什麼用的。

再看一下HashMap的狀況

/ * @author Doug Lea
 * @author Josh Bloch
 * @author Arthur van Hoff
 * @author Neal Gafter
 * @since 1.2
 */

它是直到jdk 1.2 纔出現,主要設計者是大名鼎鼎的Doug Lea,實際項目中,真的是有value爲null的狀況的。key爲null的狀況比較少見,但不表明沒有。HashMap容許null爲key和value應當是類的設計者思考讓這個類更有用的設計吧!

相關文章
相關標籤/搜索