Java Collection集合类 - HashMap 与HashTable的不同点

1.代码版本

HashTable

 * @author  Arthur van Hoff
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see     Object#equals(java.lang.Object)
 * @see     Object#hashCode()
 * @see     Hashtable#rehash()
 * @see     Collection
 * @see     Map
 * @see     HashMap
 * @see     TreeMap
 * @since JDK1.0
 */

HashMap

 * @author  Doug Lea 道格.利亚(Effective Java作者)
 * @author  Josh Bloch
 * @author  Arthur van Hoff
 * @author  Neal Gafter
 * @see     Object#hashCode()
 * @see     Collection
 * @see     Map
 * @see     TreeMap
 * @see     Hashtable
 * @since   1.2
 */

  • HashTable是java从1.1版本就提供的键值映射的数据结构

  • HashTable是线程安全的,效率比较低,慢慢就被hashMap替代了

  • HashMap是1.2版本开始提供的

2. 继承的父类
//HashTable
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable 
//HashMap
public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
  • 首先它们两个都实现了Map , 克隆 , 可序列化三个接口
  • HashMap 继承父类的是AbstractMap
  • HashTable继承的父类是Dictionary
3 . 对Null key 和Null value支持不同

HashTable :
在这里插入图片描述
不支持value ==null ,会抛出异常
在这里插入图片描述
在这里插入图片描述
不支持key == null , 在hash(k)中调用了K.hashCode()方法,相当于调用null的方法,会抛出空指针异常
hashMap:

在处理key == null时,将其hash值设为0 ,将其放在table[0]的桶中,由源码可知,key ==null的Entry只能有一个.

  • 每次传入keynull处理时,先在table[0]找keynull用新值替换旧值
  • 没有找到,则addEntry(0, null, value, 0)(将其作为新的Entry添加) ,此时的hash值被设为0
  public V put(K key, V value) {
  //key为null时,调用putFullNullKey()进行处理 
        if (key == null)
            return putForNullKey(value);
            }
  private V putForNullKey(V value) {
  // key为null时,放到table[0]的桶中
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {  // 在table[0]的桶中遍历,找到key为null的Entry 
            if (e.key == null) {
                V oldValue = e.value;  // 更改key为null的value值
                e.value = value;
                e.recordAccess(this);
                return oldValue;//返回旧值
            }
        }
        modCount++;
        addEntry(0, null, value, 0); //没有在桶中找到,直接 添加这个Entry到0号桶中
        return null;
    }
4. 初始化大小不同

HashTable的初始大小是11 , hashMap 的初始大小为16

5. 扩容大小不相同
//HashTable二倍+1扩容
 int newCapacity = (oldCapacity << 1) + 1;//扩容为2倍加1

//hashMap二倍扩容
         resize(2 * table.length);
5.加载时机

hashTable 在构造函数时初始化
hashMap 在添加第一个元素时初始化

6. 计算index值时(扰动处理)
  • HashMap对任何key都进行了扰动处理
  • HashTable对String类型的key提供可选的扰动,对于其他类型默认没有扰动
  • useAltHashing=…计算是否对字符串键的HashMap使用备选哈希函数
//hashMap 
 进行了扰动处理,降低了碰撞的几率
     h ^= k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);  //进行扰动
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
    // HashTable 
     if (useAltHashing) { //useAltHashing=...计算是否对字符串键的HashMap使用备选哈希函数 
            if (k.getClass() == String.class) {
                return sun.misc.Hashing.stringHash32((String) k);
            } else {
                int h = hashSeed ^ k.hashCode();

            
                h ^= (h >>> 20) ^ (h >>> 12);
                return h ^ (h >>> 7) ^ (h >>> 4);
             }
        } else  {
            return k.hashCode(); // 返回未扰动处理的hash值
        }

// HashTable 如果没有扰动,则hash值可能为负
//	用hash& 0[31个1]( 0x7FFFFFFF)转换为正数
      int index = (hash & 0x7FFFFFFF) % tab.length;
7. 线程安全

HashTable的公开的方法都实现了synchronized描述符 ,因而其是线程安全的.

HashMap为线程非安全的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值