publicsynchronized V put(K key, V value){ // Make sure the value is not null if (value == null) { thrownew NullPointerException(); }
// Makes sure the key is not already in the hashtable. Entry tab[] = table; int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; 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();
publicsynchronized String toString(){ int max = size() - 1; if (max == -1) return"{}";
StringBuilder sb = new StringBuilder(); Iterator<Map.Entry<K,V>> it = entrySet().iterator();
sb.append('{'); for (int i = 0; ; i++) { Map.Entry<K,V> e = it.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key.toString()); sb.append('='); sb.append(value == this ? "(this Map)" : value.toString());
if (i == max) return sb.append('}').toString(); sb.append(", "); } }
publicbooleancontains(Object o){ if (!(o instanceof Map.Entry)) returnfalse; Map.Entry entry = (Map.Entry)o; Object key = entry.getKey(); Entry[] tab = table; int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index]; e != null; e = e.next) if (e.hash==hash && e.equals(entry)) returntrue; returnfalse; }
publicbooleanremove(Object o){ if (!(o instanceof Map.Entry)) returnfalse; Map.Entry<K,V> entry = (Map.Entry<K,V>) o; K key = entry.getKey(); Entry[] tab = table; int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e.hash==hash && e.equals(entry)) { modCount++; if (prev != null) prev.next = e.next; else tab[index] = e.next;
synchronized (this) { // Write out the length, threshold, loadfactor s.defaultWriteObject();
// Write out length, count of elements s.writeInt(table.length); s.writeInt(count);
// Stack copies of the entries in the table for (int index = 0; index < table.length; index++) { Entry<K,V> entry = table[index];
while (entry != null) { entryStack = new Entry<>(0, entry.key, entry.value, entryStack); entry = entry.next; } } }
// Write out the key/value objects from the stacked entries while (entryStack != null) { s.writeObject(entryStack.key); s.writeObject(entryStack.value); entryStack = entryStack.next; } }
privatevoidreadObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { // Read in the length, threshold, and loadfactor s.defaultReadObject();
// Read the original length of the array and number of elements int origlength = s.readInt(); int elements = s.readInt();
// Compute new size with a bit of room 5% to grow but // no larger than the original size. Make the length // odd if it's large enough, this helps distribute the entries. // Guard against the length ending up zero, that's not valid. int length = (int)(elements * loadFactor) + (elements / 20) + 3; if (length > elements && (length & 1) == 0) length--; if (origlength > 0 && length > origlength) length = origlength;
// Read the number of elements and then all the key/value objects for (; elements > 0; elements--) { K key = (K)s.readObject(); V value = (V)s.readObject(); // synch could be eliminated for performance reconstitutionPut(newTable, key, value); } this.table = newTable; }
Hashtable的自定义反序列实现过程。
private void reconstitutionPut(Entry[] tab, K key, V value)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
privatevoidreconstitutionPut(Entry<K,V>[] tab, K key, V value) throws StreamCorruptedException { if (value == null) { thrownew java.io.StreamCorruptedException(); } // Makes sure the key is not already in the hashtable. // This should not happen in deserialized version. int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { thrownew java.io.StreamCorruptedException(); } } // Creates the new entry. Entry<K,V> e = tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; }
/** * 判断是否可以继续向后遍历。 * 遍历Hashtable的底层数组,看能否找到一个非空的Entry实体,如果找到返回true,否则返回 * false。 */ publicbooleanhasMoreElements(){ Entry<K,V> 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; }
/** * 遍历获取下一个元素。 * 在初始化Enumerator时传入的字段type会在这个方法中决定遍历后返回的内容是什么。 */ public T nextElement(){ Entry<K,V> 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<K,V> e = lastReturned = entry; entry = e.next; return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e); } thrownew NoSuchElementException("Hashtable Enumerator"); }