jdk 源码分析(2)java hashtable的结构及hashMap对比

来源:互联网 发布:最新网络歌曲下载 编辑:程序博客网 时间:2024/06/05 17:01
1)首先hashtable 只有一种存储结构。线性链表,这和hashmap 不同,hashmap 当数据量大是采用二叉树,可以加快查询。
  1. /**
  2. * Hashtable bucket collision list entry
  3. */
  4. private static class Entry<K,V> implements Map.Entry<K,V> {
  5. final int hash;
  6. final K key;
  7. V value;
  8. Entry<K,V> next;
  9. protected Entry(int hash, K key, V value, Entry<K,V> next) {
  10. this.hash = hash;
  11. this.key = key;
  12. this.value = value;
  13. this.next = next;
  14. }
2)对比put,hashtable 是线程安全的,但是valeu都不能为空,而hashmap可以的
  1.  //同步代码块,线程安全
  2. public synchronized V put(K key, V value) {
  3. // Make sure the value is not null
  4. if (value == null) { //value 不能为空
  5. throw new NullPointerException();
  6. }
  7. // Makes sure the key is not already in the hashtable.
  8. Entry<?,?> tab[] = table;
  9. int hash = key.hashCode();
  10. int index = (hash & 0x7FFFFFFF) % tab.length;
  11. @SuppressWarnings("unchecked")
  12. Entry<K,V> entry = (Entry<K,V>)tab[index];
  13. for(; entry != null ; entry = entry.next) {
  14. if ((entry.hash == hash) && entry.key.equals(key)) {
  15. V old = entry.value;
  16. entry.value = value;
  17. return old;
  18. }
  19. }
  20. addEntry(hash, key, value, index);
  21. return null;
  22. }
上面的方法主要是确认里面没有相同的key。
最后调用的addEntry:这是一种头部插入数据方式。头部插入要比hashmap的尾部插入快,没有理解为什么hashmap 不采用头部插入。可能为了统一treeNode的原因吧。
  1. private void addEntry(int hash, K key, V value, int index) {
  2. modCount++;
  3. Entry<?,?> tab[] = table;
  4. if (count >= threshold) {
  5. // Rehash the table if the threshold is exceeded
  6. rehash();
  7. tab = table;
  8. hash = key.hashCode();
  9. index = (hash & 0x7FFFFFFF) % tab.length;
  10. }
  11. // Creates the new entry.
  12. @SuppressWarnings("unchecked")
  13. Entry<K,V> e = (Entry<K,V>) tab[index];
  14. tab[index] = new Entry<>(hash, key, value, e);
  15. count++;
  16. }


3)get :get 简单,唯一不同就是同步

public synchronized V get(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 (V)e.value;        }    }    return null;}

4)keySet() 返回的虽然是一个set集合但是其实本身不存数据,数据还是存放在Hashtable中,包括EntrySet 等,
以前一直以为一个Set ,那么他一定存放数据了,其实错了,Set只是一堆方法。数据哪怕你放在数据库中都行,。
private class KeySet extends AbstractSet<K> {    public Iterator<K> iterator() {        return getIterator(KEYS);    }    public int size() {        return count;    }    public boolean contains(Object o) {        return containsKey(o);    }    public boolean remove(Object o) {        return Hashtable.this.remove(o) != null;    }    public void clear() {        Hashtable.this.clear();    }}


里面提到的hashmap可以参考:jdk 源码分析(1) hashmap的结构

总结: hashtable线程安全,但是查询速度慢,

其他东西不在分析,可以自己去看一下代码。源代码其实很简单。


阅读全文
0 0