Hashtable和HashMap区别

继承的父类不同

Hashtable继承自Directory,HashMap继承自AbstractMap类。但二者都实现了Map接口。

线程安全性不同

Hashtable中的方法是Synchronized的,而HashMap中的方法是非Synchronized的。在多线程并发的环境下,可以直接使用Hashtable,不需要为它的方法实现同步,但使用HashMap时就必须要自己添加同步处理。
这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedMap方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下:
Map m = Collections.synchronizedMap(new HashMap(…));

是否存在contains()方法

HashMap把Hashtable中的contains()方法去掉了,改成containsValue()和containsKey()方法,因为contains()方法容易让人引起误解。
Hashtable则保留了contains(),containsKey(),containsValue()三个方法,其中contains(),containsValue()功能相同。

key和value是否允许null值

其中key和value都是对象,并且不能包含重复的key,但可以包含重复的value。
通过Hashtable和HashMap中containsKey和containsValue方法的源码我们可以明显地看出:
Hashtable中contains()方法

public synchronized boolean contains(Object value) {
        if (value == null) {
            throw new NullPointerException();
        }

        Entry tab[] = table;
        for (int i = tab.length ; i-- > 0 ;) {   //双层for循环全局搜索,速度非常慢
            for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
                if (e.value.equals(value)) {
                    return true;
                }
            }
        }
        return false;
    }

Hashtable中,key和value都不允许出现null值
HashMap中,null可以作为键这样的键只有一个,可以有多个键所对应的值为null。当get()方法返回null值,可能是HashMap中没有该键,也可能使该键所对应的值为null。

两个遍历方式的内部实现上不同

HashMap和Hashtable都使用了Iterator。由于历史原因,Hashtable还使用了Enumration的方式。
Hashtable中的getEnumeration()和getIterator()方法

 private <T> Enumeration<T> getEnumeration(int type) {
        if (count == 0) {
            return Collections.emptyEnumeration();
        } else {
            return new Enumerator<>(type, false);
        }
    }

    private <T> Iterator<T> getIterator(int type) {
        if (count == 0) {
            return Collections.emptyIterator();
        } else {
            return new Enumerator<>(type, true);
        }
    }

hash值不同

哈希值的使用不同,Hashtable直接使用对象的hashCode(),而HashMap重新计算hash值。
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。
Hashtable在求位置索引时用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF目的是为了将负的hash值转换成正值。

内部实现使用的数组扩容和扩容方式不同

Hashtable在不指定容量的情况下默认容量为11,而HashMap为16,HashTable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
Hashtable扩容时,将容量变为原来的2倍+1,而HashMap扩容时,将容量变为原来的2倍
Hashtable扩容rehash():

 protected void rehash() {	   //当容量增加之后需要对所有元素进行rehash存储位置随即发生改变
        int oldCapacity = table.length;
        Entry<K,V>[] oldMap = table;

        // overflow-conscious code
        int newCapacity = (oldCapacity << 1) + 1;   //2倍+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<K,V>[] newMap = new Entry[newCapacity];

        modCount++;
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        boolean rehash = initHashSeedAsNeeded(newCapacity);

        table = newMap;

        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
                Entry<K,V> e = old;
                old = old.next;

                if (rehash) {
                    e.hash = hash(e.key);
                }
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newMap[index];
                newMap[index] = e;
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值