zoukankan      html  css  js  c++  java
  • Java提高(二)---- HashTable

    阅读博客

    java提高篇(二五)—–HashTable

    这篇博客由chenssy 发表与2014年4月,基于源码是jdk1.7

    ==========================

    本文针对jdk1.8的HashTable源码补充说明

    put方法

       public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
    // 直接使用key的hashCode作为hash值。
    int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }

    HashTable的key和value都不能为null

    HashTable不会对key的hashCode进行再哈希,直接使用。

    在取table的索引时,先取hash的低31位,然后对table的长度取模。这样速度比HashMap要慢。HashMap已经考虑到这个问题,所以HashMap的table长度

    是2的n次方,直接按位计算,就能得到索引,而不需要%计算了。

    put使用了synchronize修饰,多线程安全。

    在每次添加元素时,会判断当前元素数量是否超过了阈值,超过了,就要rehash,进行扩容。

    jdk1.8 rehash源码

     protected void rehash() {
            int oldCapacity = table.length;
            Entry<?,?>[] oldMap = table;
    
            // overflow-conscious code
            int newCapacity = (oldCapacity << 1) + 1;
            if (newCapacity - MAX_ARRAY_SIZE > 0) {
                if (oldCapacity == MAX_ARRAY_SIZE)
                    // Keep running with MAX_ARRAY_SIZE buckets
                    return;
                newCapacity = MAX_ARRAY_SIZE;
            }
            Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
    
            modCount++;
            threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
            table = newMap;
    
            for (int i = oldCapacity ; i-- > 0 ;) {
                for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
                    Entry<K,V> e = old;
                    old = old.next;
    
                    int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                    e.next = (Entry<K,V>)newMap[index];
                    newMap[index] = e;
                }
            }
        }

    在chenssy的博客中,下面这行有笔误,少了数组的长度。

    Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

    jdk1.8 get方法源码

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

    看完了Hashtable和HashMap,发现他们的存储结构上区别是在很小,但还是有一些区别,列举如下

    1,Hashtable是同步的,用synchronize修饰了get方法和put方法。而HashMap 没有这个修饰,

    2,HashTable不允许key和value为null,HashMap允许。

    3,HashTable使用的是Enumerator迭代器,不是fail-fast的, HashMap的迭代器更多,而且是fail-fast的。

    4,他们的hash函数不同。但这个问题吧,其实就算是HashMap在不同的jdk版本中,hash函数也不同。HashTable不会对key的hashCode进行再哈希。HashMap会对key的hashCode再hash。

    5,table的容量不容,HashMap的table容量总是2的n次方,这样方便了计算index值,提高了效率。HashTable的table容量比较随意,默认值是11,所以计算index时要费劲些。

    HashMap在性能上要好于HashTable.

    6,HashTable继承自Dictionary,实现了Map接口, HashMap继承自AbstractMap,实现了Map接口。

    HashTable比较老,jdk1.0就有了

    HashMap和 TreeMap jdk1.2才有

    ConcurrentHashMap jdk1.5才有。

    区别方面参考博客

    http://www.importnew.com/7010.html (HashMap和Hashtable的区别) 

  • 相关阅读:
    docker中查看Jenkins administrator密码
    Http缓存机制
    Jenkins启动的两种方式
    git上传项目命令方式
    windows系统.ssh文件夹脚本创建id_rsa和id_rsa.pub
    python日期加减操作
    python xlrd
    断言框架
    接口测试工具
    fake stub mock
  • 原文地址:https://www.cnblogs.com/fupeng/p/6807041.html
Copyright © 2011-2022 走看看