存储结构

数组+链表,没有HashMap的红黑树

put(K key, V value)

  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();
  5. }
  6. // Makes sure the key is not already in the hashtable.
  7. Entry<?,?> tab[] = table;
  8. int hash = key.hashCode();
  9. int index = (hash & 0x7FFFFFFF) % tab.length;
  10. @SuppressWarnings("unchecked")
  11. Entry<K,V> entry = (Entry<K,V>)tab[index];
  12. for(; entry != null ; entry = entry.next) {
  13. if ((entry.hash == hash) && entry.key.equals(key)) {
  14. V old = entry.value;
  15. entry.value = value;
  16. return old;
  17. }
  18. }
  19. addEntry(hash, key, value, index);
  20. return null;
  21. }
  22. private void addEntry(int hash, K key, V value, int index) {
  23. modCount++;
  24. Entry<?,?> tab[] = table;
  25. if (count >= threshold) {
  26. // Rehash the table if the threshold is exceeded
  27. rehash();
  28. tab = table;
  29. hash = key.hashCode();
  30. index = (hash & 0x7FFFFFFF) % tab.length;
  31. }
  32. // Creates the new entry.
  33. @SuppressWarnings("unchecked")
  34. Entry<K,V> e = (Entry<K,V>) tab[index];
  35. tab[index] = new Entry<>(hash, key, value, e);
  36. count++;
  37. }

HashTable中对hash值进行寻址的方法为 hash%数组长度 (与HashMap不同,所以不要求数组长度必须为2的n次方)

遍历table[index]所连接的链表,查找是否已经存在key与需要插入的key值相同的节点,如果存在则直接更新value,并返回旧的value。如果table[index]所连接的链表上不存在相同的key,则通过addEntry()方法将新节点加在链表的开头

get(Object key)

  1. public synchronized V get(Object key) {
  2. Entry<?,?> tab[] = table;
  3. int hash = key.hashCode();
  4. int index = (hash & 0x7FFFFFFF) % tab.length;
  5. for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
  6. if ((e.hash == hash) && e.key.equals(key)) {
  7. return (V)e.value;
  8. }
  9. }
  10. return null;
  11. }

get 方法比较简单,就是循环遍历比较,找到就返回

remove(Object key)

  1. public synchronized V remove(Object key) {
  2. Entry<?,?> tab[] = table;
  3. int hash = key.hashCode();
  4. int index = (hash & 0x7FFFFFFF) % tab.length;
  5. @SuppressWarnings("unchecked")
  6. Entry<K,V> e = (Entry<K,V>)tab[index];
  7. for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
  8. if ((e.hash == hash) && e.key.equals(key)) {
  9. modCount++;
  10. if (prev != null) {
  11. prev.next = e.next;
  12. } else {
  13. tab[index] = e.next;
  14. }
  15. count--;
  16. V oldValue = e.value;
  17. e.value = null;
  18. return oldValue;
  19. }
  20. }
  21. return null;
  22. }

这个也比较简单,也是循环查找,然后删除节点

性能上分析

  1. 计算哈希值上HashMap领先于HashTable
  2. HashTable底层是数组加链表。而HashMap底层是数组加链表加红黑树。数据多了红黑树效率遥遥领先
  3. HashTable每个暴露的方法都加了synchronized关键字。导致了性能低下。但是保证了线程安全,但是线程安全为什么不用ConcurrentHashMap呢