[closed]
@kiraSally
The 2017-07-21 11:29
Number of words4873
reading14

HashTable is pass

JAVA COLLECTIONS source


1. What is HashTable

  • The underlying hash table is used to store key-value pairs that are not null
  • Use synchronized to ensure thread safety

2. Data structure of HashTable

  • The class definition
      
  1. public class Hashtable<K.V>
  2. extends Dictionary<K.V>
  3. implements Map<K.V>, Cloneable. java.io.Serializable
  • Important global variable
      
  1. //The hash table data.
  2. // The bottom layer maintains an Entry array
  3. private transient Entry<K.V> [] table;
  4. //The total number of entries in the hash table.
  5. // Total number of elements, equivalent to the size of the HashMap
  6. private transient int count;
  7. //The load factor for the hashtable.
  8. // Load factor
  9. private float loadFactor;
  10. / * *
  11. * The table is rehashed when its size exceeds this threshold.
  12. * (The value of this field is (int)(capacity * loadFactor).)
  13. * Rehash when the threshold is exceeded
  14. * /
  15. private int threshold;
  16. / * *
  17. * The number of times this Hashtable has been structurally modified
  18. * Structural modifications are those that change the number of entries in
  19. * the Hashtable or otherwise modify its internal structure (e.g.,
  20. * rehash). This field is used to make iterators on Collection-views of
  21. * the Hashtable fail-fast. (See ConcurrentModificationException).
  22. * The fail-fast mechanism for traversal takes effect when modCount counts +1 for structural changes
  23. * /
  24. private transient int modCount = 0;
  • The constructor
      
  1. / * *
  2. * initialCapacity Default 11
  3. * loadFactor defaults to 0.75
  4. * /
  5. public Hashtable(a) {
  6. this(11. 0.75 f);
  7. }
  8. / * *
  9. * Basically consistent with JDK1.7's HashMap
  10. * @param initialCapacity The default capacity is 11
  11. * @param loadFactor the loadFactor defaults to 0.75
  12. * /
  13. public Hashtable(int initialCapacity. float loadFactor) {
  14. if (initialCapacity < 0)
  15. throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
  16. if (loadFactor < = 0 || Float.isNaN(loadFactor))
  17. throw new IllegalArgumentException("Illegal Load: "+loadFactor);
  18. // The difference is that cap is not forced to power 2. When initCap=0, it defaults to 1
  19. if (initialCapacity= =0)
  20. initialCapacity = 1;
  21. this.loadFactor = loadFactor;
  22. table = new Entry[initialCapacity];
  23. threshold = (int)Math.min(initialCapacity * loadFactor. MAX_ARRAY_SIZE + 1);
  24. UseAltHashing: Boolean; if true, execute another hashed string key to reduce hash collisions due to weak hash calculations
  25. useAltHashing = sun.misc.VM.isBooted(a) &&
  26. (initialCapacity > = Holder.ALTERNATIVE_HASHING_THRESHOLD);
  27. }

3. The HashTable of storage

  • Put method parsing
      
  1. public synchronized V put(K key. V value) {
  2. // Make sure the value is not null
  3. if (value = = null) {
  4. throw new NullPointerException(a);
  5. }
  6. // Makes sure the key is not already in the hashtable.
  7. // Make sure the key is not in the hashtable
  8. // First, hash the key and index to determine its position in table[]
  9. // Next, iterate over the list at the index position. If the list at that position has the same key, replace value and return the old value
  10. Entry tab[] = table;
  11. int hash = hash(key);
  12. // Calculate the subscript, using the % method, which is nowhere near as good as the bitwise operations of HashMap (one of the reasons HashTable is not recommended)
  13. int index = (hash & 0x7FFFFFFF) % tab.length;
  14. for (Entry<K.V> e = tab[index] ; e ! = null ; e = e.next) {
  15. / / use equals more directly, and much HashMap layer address is ` ((k = e.k ey) = = key | | key. Equals (k)) `
  16. if ((e.hash = = hash) && e.key.equals(key)) {
  17. V old = e.value;
  18. e.value = value;
  19. return old;
  20. }
  21. }
  22. // Structural change operation modCount counts +1
  23. modCount+ +;
  24. // select addEntry to encapsulate the logic
  25. if (count > = threshold) {
  26. // Rehash the table if the threshold is exceeded
  27. // If the threshold is exceeded, rehash is performed
  28. rehash(a);
  29. tab = table;
  30. hash = hash(key);
  31. index = (hash & 0x7FFFFFFF) % tab.length;
  32. }
  33. // Creates the new entry.
  34. // Insert the value, return null
  35. Entry<K.V> e = tab[index];
  36. // Create a new Entry node, insert the new Entry into the index position of the Hashtable, and set e to the next element of the new Entry
  37. tab[index] = new Entry< > (hash. key. value. e);
  38. //size++
  39. count+ +;
  40. return null;
  41. }
  • Rehash method resolution
      
  1. protected void rehash(a) {
  2. int oldCapacity = table.length;
  3. Entry<K.V> [] oldMap = table;// Use temporary copies to keep current data timely (see JAVA's 'observer' mode implementation)
  4. // overflow-conscious code
  5. // Double the original capacity +1
  6. int newCapacity = (oldCapacity << 1) + 1;
  7. if (newCapacity - MAX_ARRAY_SIZE > 0) {
  8. if (oldCapacity = = MAX_ARRAY_SIZE)
  9. // Keep running with MAX_ARRAY_SIZE buckets
  10. return;
  11. newCapacity = MAX_ARRAY_SIZE;
  12. }
  13. Entry<K.V> [] newMap = new Entry[newCapacity];
  14. // Rehash is also a structural change, modCount counts +1
  15. modCount+ +;
  16. threshold = (int)Math.min(newCapacity * loadFactor. MAX_ARRAY_SIZE + 1);
  17. boolean currentAltHashing = useAltHashing;
  18. useAltHashing = sun.misc.VM.isBooted(a) && (newCapacity > = Holder.ALTERNATIVE_HASHING_THRESHOLD);
  19. boolean rehash = currentAltHashing ^ useAltHashing;
  20. table = newMap;
  21. // iterate over the old array and reassign to the new array
  22. for (int i = oldCapacity ; i-- > 0 ;) {
  23. for (Entry<K.V> old = oldMap[i] ; old ! = null ; ) {
  24. Entry<K.V> e = old;
  25. old = old.next;
  26. if (rehash) {
  27. e.hash = hash(e.key);// rehash
  28. }
  29. // It's still the % operation
  30. int index = (e.hash & 0x7FFFFFFF) % newCapacity;
  31. e.next = newMap[index];
  32. newMap[index] = e;
  33. }
  34. }
  35. }
  • Get method parsing
      
  1. public synchronized V get(Object key) {
  2. Entry tab[] = table;// Use temporary copies to keep current data timely (see JAVA's 'observer' mode implementation)
  3. int hash = hash(key);
  4. int index = (hash & 0x7FFFFFFF) % tab.length;
  5. for (Entry<K.V> e = tab[index] ; e ! = null ; e = e.next) {
  6. if ((e.hash = = hash) && e.key.equals(key)) {
  7. return e.value;
  8. }
  9. }
  10. return null;
  11. }

4. The HashTable iteration

  • A Hashtable can be traversed in several ways:
      
  1. //1, use keys()
  2. Enumeration<String> en1 = table.keys(a);
  3. while(en1.hasMoreElements()) {
  4. en1.nextElement(a);
  5. }
  6. //2.
  7. Enumeration<String> en2 = table.elements(a);
  8. while(en2.hasMoreElements()) {
  9. en2.nextElement(a);
  10. }
  11. // select * from keySet();
  12. Iterator<String> it1 = table.keySet().iterator(a);
  13. while(it1.hasNext()) {
  14. it1.next(a);
  15. }
  16. // use entrySet()
  17. Iterator<Entry<String. String>> it2 = table.entrySet().iterator(a);
  18. while(it2.hasNext()) {
  19. it2.next(a);
  20. }

5. Comparison of HashTable and HashMap

  • HashTable is based on the Dictionary class, while HashMap is based on AbstractMap. Dictionary is the abstract parent of any class that maps keys to corresponding values, and AbstractMap is an implementation based on the Map interface to minimize the effort required to implement this interface.
  • The key and value of a HashMap can be null, while the key and value of a Hashtable cannot be null. When a HashMap encounters a null key, putForNullKey is called (put it into table[0]), but value is not processed. When Hashtable encounters null, NullPointerException is returned.
  • The Hashtable method is synchronous, while the HashMap method is not. Nearly all public methods in a Hashtable are synchronized, and some methods are implemented internally with synchronized code blocks.
  • HashTable, due to its use of sync and % operations (and associated algorithmic implementations), has a lower performance than HashMap, and is therefore highly discouraged from continuing to use HashTable. HashMap is recommended in non-competitive environments. ConcurrentHashMap is recommended in multi-threaded environments

  • Table of contents


      • COLLECTIONS 3
      • HashTable is pass
      • HashSet is pass
      • HashMap is pass
      • JAVA 3
      • HashTable is pass
      • HashSet is pass
      • HashMap is pass
      • The source code 3
      • HashTable is pass
      • HashSet is pass
      • HashMap is pass
    • The following [tags] will be used to mark this contribution:
    • Downloading a Client
    • Focus on developers
    • Report problems and suggestions
    • Contact us

Add a new annotation
Save the cancel
This annotation is viewable only to you and the author until the author makes it public.

Save the cancel

Modify save cancel delete

  • private
  • public
  • delete

Check out the five earlier replies

Respond to comments