Java-Collection源码分析(十)——hashTable

来源:互联网 发布:淘宝新店铺一天刷几单 编辑:程序博客网 时间:2024/05/22 06:15

 Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,不允许value值为null,采用单向链表的形式。具体操作与单向链表相同。

源码分析

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable {    //hashtable 的数据    private transient Entry<?,?>[] table;    //哈希表中的条目总数。    private transient int count;    //当其大小超过此阈值时,表被重新打开。 (该字段的值为(int)(capacity * loadFactor)。)    private int threshold;    //哈希表的负载因子。    private float loadFactor;    private transient int modCount = 0;    private static final long serialVersionUID = 1421746759512286392L;    //构造一个新的,空的散列表,具有指定的初始容量和指定的负载因子。    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);    }    //构造一个新的空的散列表,具有指定的初始容量和默认负载因子(0.75)。    public Hashtable(int initialCapacity) {        this(initialCapacity, 0.75f);    }    //构造一个新的,空的散列表,默认的初始容量(11)和负载因子(0.75)。    public Hashtable() {        this(11, 0.75f);    }    //使用与给定地图相同的映射构造新的散列表。 创建散列表的初始容量足以容纳给定地图中的映射和默认负载因子(0.75)。    public Hashtable(Map<? extends K, ? extends V> t) {        this(Math.max(2*t.size(), 11), 0.75f);        putAll(t);    }    //返回此哈希表中的key的数量    public synchronized int size() {        return count;    }    //测试这个哈希表是否将值映射到值。    public synchronized boolean isEmpty() {        return count == 0;    }    //返回此散列表中键的枚举。    public synchronized Enumeration<K> keys() {        return this.<K>getEnumeration(KEYS);    }    //返回此散列表中值的枚举。 对返回的对象使用枚举方法来顺序获取元素。    public synchronized Enumeration<V> elements() {        return this.<V>getEnumeration(VALUES);    }//测试一些键映射到这个散列表中的指定值。 此操作比containsKey方法更昂贵。//请注意,此方法的功能与containsValue(它是集合框架中的Map接口的一部分)的功能相同。    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;    }    //如果此哈希表将一个或多个键映射到此值,则返回true。    //请注意,此方法的功能与contains的功能相同。    public boolean containsValue(Object value) {        return contains(value);    }    //测试指定的对象是否在此哈希表中的键。    public synchronized boolean containsKey(Object key) {        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {            if ((e.hash == hash) && e.key.equals(key)) {                return true;            }        }        return false;    }    //返回指定键映射到的值,如果此映射不包含该键的映射,则返回null。    //更正式地,如果该映射包含从key到value的映射,使得(key.equals(k)),则该方法返回value; 否则返回null。(最多可以有一个这样的映射。)    public synchronized V get(Object key) {        Entry<?,?> tab[] = table;        int hash = key.hashCode();        //计算索引值        int index = (hash & 0x7FFFFFFF) % tab.length;        //在key对应的Entry链表下,找到hash和key值与输入可以都相等的元素        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {            if ((e.hash == hash) && e.key.equals(key)) {                return (V)e.value;            }        }        return null;    }    //要分配的数组的最大大小。 一些虚拟机在阵列中保留一些头文字。     //尝试分配较大的数组可能会导致OutOfMemoryError:请求的数组大小超过VM限制    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;        //增加这个散列表的内部重组能力,从而更有效地适应和访问其条目。     //当哈希表中的键数超过此散列表的容量和负载因子时,将自动调用此方法。    protected void rehash() {        int oldCapacity = table.length;        Entry<?,?>[] oldMap = table;        //新容量的大小设置为旧容量的两倍加一        int newCapacity = (oldCapacity << 1) + 1;        //如果旧容量等于最大容量,新容器容量超过最大容量,将容量保持到最大容量        if (newCapacity - MAX_ARRAY_SIZE > 0) {            if (oldCapacity == MAX_ARRAY_SIZE)                return;            newCapacity = MAX_ARRAY_SIZE;        }        //创建新的Entry链表        Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];        //统计数+1        modCount++;        //重新计算阙值大小        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);        table = newMap;//将旧的hashtable的内容复制到新的hashtable中        for (int i = oldCapacity ; i-- > 0 ;) {            for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {                Entry<K,V> e = old;                //将next往前移动一个位置                old = old.next;//重新计算索引值                int index = (e.hash & 0x7FFFFFFF) % newCapacity;                //将e的next元素指向新的hashtable中索引链表的首元素                e.next = (Entry<K,V>)newMap[index];                //将e复制到新的hashtable中,作为链表的首元素,之前新hashtable中的元素往后移动一个位置                newMap[index] = e;            }        }    }    private void addEntry(int hash, K key, V value, int index) {        modCount++;//获取hashtable        Entry<?,?> tab[] = table;        if (count >= threshold) {            //如果超过阈值,则重新排列表            rehash();            tab = table;            hash = key.hashCode();            index = (hash & 0x7FFFFFFF) % tab.length;        }        //创建一个新的Entry        Entry<K,V> e = (Entry<K,V>) tab[index];        //将e连接在插入Entry的next        tab[index] = new Entry<>(hash, key, value, e);        count++;    }    /将指定的key映射到此散列表中指定的value。 key和value都不能是null。    //可以通过使用等于原始key的key调用get方法来检索该值。    public synchronized V put(K key, V value) {        //确保value不为null        if (value == null) {            throw new NullPointerException();        }        //确保key不在哈希表中。        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        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;            }        }        //如果没有key和hash匹配的元素,则创建并添加新的entry        addEntry(hash, key, value, index);        return null;    }    //从这个散列表中删除键(及其对应的值)。如果键不在哈希表中,此方法不执行任何操作。    public synchronized V remove(Object key) {        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        Entry<K,V> e = (Entry<K,V>)tab[index];        for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {            if ((e.hash == hash) && e.key.equals(key)) {                modCount++;                if (prev != null) {                    prev.next = e.next;                } else {                    tab[index] = e.next;                }                count--;                V oldValue = e.value;                e.value = null;                return oldValue;            }        }        return null;    }    //将指定地图的所有映射复制到此散列表。 这些映射将取代这个散列表对当前指定地图中的任何键的任何映射。    public synchronized void putAll(Map<? extends K, ? extends V> t) {        for (Map.Entry<? extends K, ? extends V> e : t.entrySet())            put(e.getKey(), e.getValue());    }    //清除此散列表,使其不包含键。    public synchronized void clear() {        Entry<?,?> tab[] = table;        modCount++;        for (int index = tab.length; --index >= 0; )            tab[index] = null;        count = 0;    }    //创建这个散列表的浅拷贝。 哈希表本身的所有结构都被复制,但是键和值不被克隆。 这是一个相对昂贵的操作。    public synchronized Object clone() {        try {            Hashtable<?,?> t = (Hashtable<?,?>)super.clone();            t.table = new Entry<?,?>[table.length];            for (int i = table.length ; i-- > 0 ; ) {                t.table[i] = (table[i] != null)                    ? (Entry<?,?>) table[i].clone() : null;            }            t.keySet = null;            t.entrySet = null;            t.values = null;            t.modCount = 0;            return t;        } catch (CloneNotSupportedException e) {            // this shouldn't happen, since we are Cloneable            throw new InternalError(e);        }    }     //根据Map界面中的定义,将指定的对象与此Map进行比较以相等。    public synchronized boolean equals(Object o) {        if (o == this)            return true;        if (!(o instanceof Map))            return false;        Map<?,?> t = (Map<?,?>) o;        if (t.size() != size())            return false;        try {            Iterator<Map.Entry<K,V>> i = entrySet().iterator();            while (i.hasNext()) {                Map.Entry<K,V> e = i.next();                K key = e.getKey();                V value = e.getValue();                if (value == null) {                    if (!(t.get(key)==null && t.containsKey(key)))                        return false;                } else {                    if (!value.equals(t.get(key)))                        return false;                }            }        } catch (ClassCastException unused)   {            return false;        } catch (NullPointerException unused) {            return false;        }        return true;    }//将每个条目的value替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。    public synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {        Objects.requireNonNull(function);     // 需要明确检查        final int expectedModCount = modCount;        Entry<K, V>[] tab = (Entry<K, V>[])table;        for (Entry<K, V> entry : tab) {            while (entry != null) {                entry.value = Objects.requireNonNull(                    function.apply(entry.key, entry.value));                entry = entry.next;                if (expectedModCount != modCount) {                    throw new ConcurrentModificationException();                }            }        }    }    //如果指定的key还没有与value相关联(或映射到null)将其与给定value相关联并返回null,否则返回当前value。    public synchronized V putIfAbsent(K key, V value) {        Objects.requireNonNull(value);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        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;                if (old == null) {                    entry.value = value;                }                return old;            }        }        addEntry(hash, key, value, index);        return null;    }    //只有当目标映射到指定的值时,才能删除指定key的条目。    public synchronized boolean remove(Object key, Object value) {        Objects.requireNonNull(value);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {            if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {                modCount++;                if (prev != null) {                    prev.next = e.next;                } else {                    tab[index] = e.next;                }                count--;                e.value = null;                return true;            }        }        return false;    }    //仅当当前映射到指定的value时,才能替换指定key的条目。    public synchronized boolean replace(K key, V oldValue, V newValue) {        Objects.requireNonNull(oldValue);        Objects.requireNonNull(newValue);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (; e != null; e = e.next) {            if ((e.hash == hash) && e.key.equals(key)) {                if (e.value.equals(oldValue)) {                    e.value = newValue;                    return true;                } else {                    return false;                }            }        }        return false;    }    //只有当目标映射到某个值时,才能替换指定键的条目。    public synchronized V replace(K key, V value) {        Objects.requireNonNull(value);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (; e != null; e = e.next) {            if ((e.hash == hash) && e.key.equals(key)) {                V oldValue = e.value;                e.value = value;                return oldValue;            }        }        return null;    }    //如果指定的键尚未与值相关联(或映射到null),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非为null。    public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {        Objects.requireNonNull(mappingFunction);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (; e != null; e = e.next) {            if (e.hash == hash && e.key.equals(key)) {                // Hashtable not accept null value                return e.value;            }        }        V newValue = mappingFunction.apply(key);        if (newValue != null) {            addEntry(hash, key, newValue, index);        }        return newValue;    }    //如果指定的键的值存在且非空,则尝试计算给定键的新映射及其当前映射的值。    public synchronized V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {            if (e.hash == hash && e.key.equals(key)) {                V newValue = remappingFunction.apply(key, e.value);                if (newValue == null) {                    modCount++;                    if (prev != null) {                        prev.next = e.next;                    } else {                        tab[index] = e.next;                    }                    count--;                } else {                    e.value = newValue;                }                return newValue;            }        }        return null;    }    //尝试计算指定key及其当前映射value的映射(如果没有当前映射,则为null)。    public synchronized V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {            if (e.hash == hash && Objects.equals(e.key, key)) {                V newValue = remappingFunction.apply(key, e.value);                if (newValue == null) {                    modCount++;                    if (prev != null) {                        prev.next = e.next;                    } else {                        tab[index] = e.next;                    }                    count--;                } else {                    e.value = newValue;                }                return newValue;            }        }        V newValue = remappingFunction.apply(key, null);        if (newValue != null) {            addEntry(hash, key, newValue, index);        }        return newValue;    }    //如果指定的key尚未与value相关联或与null相关联,则将其与给定的非空值相关联。    public synchronized V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);        Entry<?,?> tab[] = table;        int hash = key.hashCode();        int index = (hash & 0x7FFFFFFF) % tab.length;        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>)tab[index];        for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {            if (e.hash == hash && e.key.equals(key)) {                V newValue = remappingFunction.apply(e.value, value);                if (newValue == null) {                    modCount++;                    if (prev != null) {                        prev.next = e.next;                    } else {                        tab[index] = e.next;                    }                    count--;                } else {                    e.value = newValue;                }                return newValue;            }        }        if (value != null) {            addEntry(hash, key, value, index);        }        return value;    }     private static class Entry<K,V> implements Map.Entry<K,V> {        final int hash;        final K key;        V value;        Entry<K,V> next;        protected Entry(int hash, K key, V value, Entry<K,V> next) {            this.hash = hash;            this.key =  key;            this.value = value;            this.next = next;        }        @SuppressWarnings("unchecked")        protected Object clone() {            return new Entry<>(hash, key, value,                                  (next==null ? null : (Entry<K,V>) next.clone()));        }        // Map.Entry Ops        public K getKey() {            return key;        }        public V getValue() {            return value;        }        public V setValue(V value) {            if (value == null)                throw new NullPointerException();            V oldValue = this.value;            this.value = value;            return oldValue;        }        public boolean equals(Object o) {            if (!(o instanceof Map.Entry))                return false;            Map.Entry<?,?> e = (Map.Entry<?,?>)o;            return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&               (value==null ? e.getValue()==null : value.equals(e.getValue()));        }        public int hashCode() {            return hash ^ Objects.hashCode(value);        }        public String toString() {            return key.toString()+"="+value.toString();        }    }    // Types of Enumerations/Iterations    private static final int KEYS = 0;    private static final int VALUES = 1;    private static final int ENTRIES = 2;    //一个哈希表枚举器类。 此类实现了枚举和迭代器接口,但是可以使用禁用Iterator方法创建单个实例。     //这是必要的,以避免无意中通过传递枚举来增加用户授予的功能。    private class Enumerator<T> implements Enumeration<T>, Iterator<T> {        Entry<?,?>[] table = Hashtable.this.table;        int index = table.length;        Entry<?,?> entry;        Entry<?,?> lastReturned;        int type;        //指示此枚举器是否用作迭代器或枚举。 (true - >迭代器)。        boolean iterator;        //迭代器认为后台Hashtable应该具有的modCount值。 如果这个期望被违反,迭代器就检测到并发修改。        protected int expectedModCount = modCount;        Enumerator(int type, boolean iterator) {            this.type = type;            this.iterator = iterator;        }        public boolean hasMoreElements() {            Entry<?,?> e = entry;            int i = index;            Entry<?,?>[] t = table;            /* Use locals for faster loop iteration */            while (e == null && i > 0) {                e = t[--i];            }            entry = e;            index = i;            return e != null;        }        @SuppressWarnings("unchecked")        public T nextElement() {            Entry<?,?> et = entry;            int i = index;            Entry<?,?>[] t = table;            /* Use locals for faster loop iteration */            while (et == null && i > 0) {                et = t[--i];            }            entry = et;            index = i;            if (et != null) {                Entry<?,?> e = lastReturned = entry;                entry = e.next;                return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);            }            throw new NoSuchElementException("Hashtable Enumerator");        }        // Iterator methods        public boolean hasNext() {            return hasMoreElements();        }        public T next() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            return nextElement();        }        public void remove() {            if (!iterator)                throw new UnsupportedOperationException();            if (lastReturned == null)                throw new IllegalStateException("Hashtable Enumerator");            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            synchronized(Hashtable.this) {                Entry<?,?>[] tab = Hashtable.this.table;                int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;                @SuppressWarnings("unchecked")                Entry<K,V> e = (Entry<K,V>)tab[index];                for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) {                    if (e == lastReturned) {                        modCount++;                        expectedModCount++;                        if (prev == null)                            tab[index] = e.next;                        else                            prev.next = e.next;                        count--;                        lastReturned = null;                        return;                    }                }                throw new ConcurrentModificationException();            }        }    }}
rehash过程中,hashtable旧元素的复制过程:



原创粉丝点击