标签:hashcode 并发 checked public serial put element ext dde
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
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); } public Hashtable(int initialCapacity) { this(initialCapacity, 0.75f); } public Hashtable() { this(11, 0.75f); } public Hashtable(Map<? extends K, ? extends V> t) { this(Math.max(2*t.size(), 11), 0.75f); putAll(t); }
public static void main(String[] args) { Hashtable<Integer, String> tb = new Hashtable<Integer,String>(); tb.put(1, "BUPT"); tb.put(2, "PKU"); tb.put(3, "THU"); Iterator<Entry<Integer, String>> iter = tb.entrySet().iterator(); while(iter.hasNext()){ Entry<?, ?> entry = (Entry<?, ?>) iter.next(); //此处会抛出异常 System.out.println(entry.getValue()); if("THU".equals(entry.getValue())){ tb.remove(entry.getKey()); } } } /* 输出结果如下: THU Exception in thread "main" java.util.ConcurrentModificationException at java.util.Hashtable$Enumerator.next(Hashtable.java:1367) at ali.Main.main(Main.java:16) */
ConcurrentModificationException异常,每一次修改hashtable中的数据都更新modCount的值,而迭代器Enumerator<T>的next方法会判断modCount != expectedModCount
public T next() { //首先判断modCount和expectedModCount是否相等 //由于在主程序中Hashtable对象通过tb.remove()方法修改了modCount的值,使得expectedModCount和modCount不相等而抛出异常 //解决办法就是将tb.remove()方法替换为iter.remove()方法 if (modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); }
//该方法在remove元素的同时修改了modCount和expectedModCount的值 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(); } }
可以看出,每次插入都要遍历一次链表,每次都是O(n),效率比HashMap要低下,HashMap一般为红黑树内O(LogN),链表内O(n),直接定位则为1
public synchronized V put(K key, V value) { //值不允许为null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; //得到键的hash int hash = key.hashCode(); //得到对应hash在数组中的桶索引 int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") //得到桶中链表头节点 Entry<K,V> entry = (Entry<K,V>)tab[index]; //从头开始遍历 for(; entry != null ; entry = entry.next) { //一旦hash值相等并且键相等,替换旧值 if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } //如果没有找到相同键,那么添加新节点 addEntry(hash, key, value, index); return null; }
private void addEntry(int hash, K key, V value, int index) { modCount++; Entry<?,?> tab[] = table; //如果尺寸超过了阈值,进行rehash if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash(); tab = table; hash = key.hashCode(); index = (hash & 0x7FFFFFFF) % tab.length; } // Creates the new entry. @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; }
public synchronized V get(Object key) { Entry<?,?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; //遍历所有元素,哈希值和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; }
Java底层类和源码分析系列-HashTable底层架构和源码分析
标签:hashcode 并发 checked public serial put element ext dde
原文地址:https://www.cnblogs.com/starcrm/p/12678770.html