每日一道Java 基础面试题 — HashMap和HashTable的区别

1、两者父类不同

HashMap是继承自AbstractMap类,而Hashtable是继承自Dictionary类。
不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。

2、对外提供的接口不同

Hashtable比HashMap多提供了elments() 和contains() 两个方法。

在这里插入图片描述
在这里插入图片描述

elments() 方法继承自Hashtable的父类Dictionnary。
elements() 方法用于返回此Hashtable中的value的枚举。
在这里插入图片描述

contains()方法判断该Hashtable是否包含传入的value。
在这里插入图片描述
它的作用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。

3、对null的支持不同

Hashtable:key和value都不能为null。

HashMap:

  • key可以为null,但是这样的key只能有一个,因为必须保证key的唯一性;
  • 可以有多个key值对应的value为null。

4、安全性不同

HashMap是线程不安全的

在多线程并发的环境下,可能会产生死锁等问题,因此需要开发人员自
己处理多线程的安全问题。

Hashtable是线程安全的

它的每个方法上都有synchronized 关键字,因此可直接用于多线程中。

虽然HashMap是线程不安全的,但是它的效率远远高于Hashtable,

这样设计是合理的,因为大部分的使用场景都是单线程。

当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。

ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。
因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。

5、初始容量大小和每次扩充容量大小不同

在这里插入图片描述
map集合长度大于上一次扩容前长度1.75倍的时候再扩容。每次扩容都是原来的两倍
例如:初始大小为 16 ,扩容因子 0.75 ,当容量为12的时候,比例已经是0.75 。
触发扩容,扩容后的大小为 32.

在这里插入图片描述
即当 元素个数 超过 容量长度的0.75倍时,进行扩容。
扩容增量:2*原数组长度+1,如 HashTable的容量为11,一次扩容后是容量为23。

6、计算hash值的方法不同

HashMap中:

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

HashMap 中的key值可以为null
key值的hash值的计算方法为:key的 hash 值高16位不变,低16位与高16位 异或 作为key最终的hash值。(h>>>16,表示无符号右移16位,高位补0)

Hashtable中

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;
    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线程安全是因为添加了 synchronized 关键字,同时 Hashtable key值是不可以为空的。

其中 int index = (hash & 0x7FFFFFFF) % tab.length;

为了在hash为负值的情况下,去掉起符号位,所以和 0x7FFFFFFF进行&操作。
0x7FFFFFFF二进制0111 1111 1111 1111 1111 1111 1111 1111,负数与其进行&操作将产生正整数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值