HashTable源码分析

来源:互联网 发布:java代码实现充值功能 编辑:程序博客网 时间:2024/06/16 05:53

版本说明:jdk1.7.0_79

概述

Hashtable已经成为过时的集合,但是仍有必要研究一下其源码,而且面试中也经常被问到Hashtable与HashMap的区别。Hashtable是线程安全的,但是Collections类中已经针对集合的线程安全有了新的实现,如果考虑到线程安全,请使用Collections.synchronizedMap(map)来代替Hashtable。
Map线程安全几种实现方法

类声明

public class Hashtable<K,V> extends Dictionary<K,V> implements  Map<K,V>,Cloneable,Serializablepublic class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

通过比较可知,HashMap和HashTable都实现了Map接口,cloneable接口,Serializable接口。但HashMap继承于AbstractMap类,而Hashtable继承于Dictionary类

属性

    //用来存储元素    private transient Entry<K,V>[] table;    //元素总个数    private transient int count;    //阈值    private int threshold;    //加载因子    private float loadFactor;    private transient int modCount = 0;    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;    transient int hashSeed;

构造方法

    public Hashtable(int initialCapacity, float loadFactor) {        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal Load: "+loadFactor);        if (initialCapacity==0)            initialCapacity = 1;        this.loadFactor = loadFactor;        table = new Entry[initialCapacity];        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);        initHashSeedAsNeeded(initialCapacity);    }    public Hashtable(int initialCapacity) {        this(initialCapacity, 0.75f);    }    public Hashtable() {        //初始容量默认为11,加载因子默认为0.75        this(11, 0.75f);    }    public Hashtable(Map<? extends K, ? extends V> t) {        this(Math.max(2*t.size(), 11), 0.75f);        putAll(t);    }

HashTable有4个构造方法。
若没有指定初始容量和加载因子,则初始容量默认为11(HashMap为16),加载因子默认为0.75(同HashMap)

put方法

    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;        //计算key的hash码        int hash = hash(key);        //通过hash定位key在数组中的索引        int index = (hash & 0x7FFFFFFF) % tab.length;        //遍历链表,查询key是否存在        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {            //如果存在,则覆盖            if ((e.hash == hash) && e.key.equals(key)) {                V old = e.value;                e.value = value;                return old;            }        }        modCount++;        //判断元素总个数是否达到阈值,是则进行再哈希(以保持元素均匀分布)        if (count >= threshold) {            // Rehash the table if the threshold is exceeded            rehash();            tab = table;            hash = hash(key);            index = (hash & 0x7FFFFFFF) % tab.length;        }        // Creates the new entry.        Entry<K,V> e = tab[index];        tab[index] = new Entry<>(hash, key, value, e);        count++;        return null;    }

Hashtable存放的键值对中的值不能为null。

判断key是否存在,通过(e.hash == hash) && e.key.equals(key)。如果该key已经存在,则覆盖。

get方法

    public synchronized V get(Object key) {        Entry tab[] = table;        //计算key的hash        int hash = hash(key);        //定位key在table数组中的位置        int index = (hash & 0x7FFFFFFF) % tab.length;        //遍历table数组查找key        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {            //key存在(key的hash相等,且equals()相等),则返回对应的值            if ((e.hash == hash) && e.key.equals(key)) {                return e.value;            }        }        //key不存在,返回null        return null;    }

HashTable与HashMap的区别

  1. Hashtable和HashMap都实现了Map接口,但Hashtable继承于Dictionary类,而HashMap继承于AbstractMap类。
  2. Hashtable是线程安全的,而HashMap是非线程安全的。因此,Hashtable比HashMap的效率要低。
  3. Hashtable的key和value都不能为null。而HashMap的key和value都可以为null。Hashtable/HashMap与key/value为null的关系
  4. HashTable使用Enumeration,HashMap使用Iterator。
  5. Hashtable的初始容量默认为11,HashMap的初始容量为16。
0 0
原创粉丝点击