Java系列(面试必备):HashMap和Hashtable的区别!

Java系列(面试必备):HashMap 和 Hashtable 的 6 个区别!


前言

今天博主将为大家分享:Java系列(面试必备):HashMap 和 Hashtable 的 6 个区别!不喜勿喷,如有异议欢迎讨论!首先推荐结合博主的这篇文章进行阅读===>Java系列(面试必备):简单的hashCode和equals面试题,有好多坑!

HashMap 和 Hashtable 是 Java 开发程序员必须要掌握的,也是在各种 Java 面试场合中必须会问到的。


一:线程安全

Hashtable 是线程安全的,HashMap 不是线程安全的。

为什么说 HashTable 是线程安全的?

来看下 Hashtable 的源码,Hashtable 所有的元素操作如put-get等都是 synchronized 修饰的,而 HashMap 并没有。

public synchronized V put(K key, V value);
public synchronized V get(Object key);
...

二:性能优劣

既然 Hashtable 是线程安全的,每个方法都要阻塞其他线程,所以 Hashtable 性能较差,HashMap 性能较好,使用更广。

如果要线程安全又要保证性能,建议使用 JUC 包下的 ConcurrentHashMap。


三:NULL

Hashtable 是不允许键或值为 null 的,HashMap 的键值则都可以为 null。

那么问题来了,为什么 Hashtable 是不允许 KEY 和 VALUE 为 null, 而 HashMap 则可以?

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;
        int hash = key.hashCode();

        ...

} 

HashMap hash 方法逻辑:

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

可以看出 Hashtable key 为 null 会直接抛出空指针异常,value 为 null 手动抛出空指针异常,而 HashMap 的逻辑对 null 作了特殊处理。


四:实现方式

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

可以看出两者继承的类不一样,Hashtable 继承了 Dictionary类,而 HashMap 继承的是 AbstractMap 类。

Dictionary 是 JDK 1.0 添加的,貌似没人用过这个,我也没用过。。


五:容量扩容

HashMap 的初始容量为:16,Hashtable 初始容量为:11,两者的负载因子默认都是:0.75。

/**
 * Constructs a new, empty hashtable with a default initial capacity (11)
 * and load factor (0.75).
 */
public Hashtable() {
    this(11, 0.75f);
}

/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

当现有容量大于总容量 * 负载因子时,HashMap 扩容规则为当前容量翻倍,Hashtable 扩容规则为当前容量翻倍 + 1。


六:迭代器

HashMap 中的 Iterator 迭代器是 fail-fast 的,而 Hashtable 的 Enumerator 不是 fail-fast 的。关于 fail-fast 给大家推荐一个前辈的博文=>Java集合详解3:Iterator,fail-fast机制与比较器

所以,当其他线程改变了HashMap 的结构,如:增加、删除元素,将会抛出 ConcurrentModificationException 异常,而 Hashtable 则不会。

可以来看下这个区别的演示:

/**
 * 
 * @author ChenYongJia
 * @Date 2019年6月27日 晚上21:26
 * @Email chen87647213@163.com
 */
public static void main(String[] args) {
    Map<String, String> hashtable = new Hashtable<>();
    hashtable.put("t1", "1");
    hashtable.put("t2", "2");
    hashtable.put("t3", "3");

    Enumeration<Map.Entry<String, String>> iterator1 = (Enumeration<Map.Entry<String, String>>) hashtable.entrySet().iterator();
    hashtable.remove(iterator1.nextElement().getKey());
    while (iterator1.hasMoreElements()) {
        System.out.println(iterator1.nextElement());
    }

    Map<String, String> hashMap = new HashMap<>();
    hashMap.put("h1", "1");
    hashMap.put("h2", "2");
    hashMap.put("h3", "3");

    Iterator<Map.Entry<String, String>> iterator2 = hashMap.entrySet().iterator();
    hashMap.remove(iterator2.next().getKey());
    while (iterator2.hasNext()) {
        System.out.println(iterator2.next());
    }

}

输出信息:

t2=2
t1=1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1476)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1474)
    at cn.javastack.Test.main(Test.java:37)

所以,这条同样也是 Enumeration 和 Iterator 的区别。


到这里:Java系列(面试必备):HashMap 和 Hashtable 的 6 个区别!,分享完毕了,快去试试吧!


最后

  • 更多参考精彩博文请看这里:《陈永佳的博客》

  • 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!


  • 19
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: HashMapHashtable都是Java中用于存储键值对的数据结构,但是它们有一些显著的不同点: 1. 线程安全:Hashtable是线程安全的,而HashMap是线程不安全的。 2. 允许空键和空值:HashMap允许空键和空值,而Hashtable不允许空键和空值。 3. 性能:因为HashMap是线程不安全的,所以在单线程环境中它的性能比Hashtable好。 4. 方法:HashMap的put()和remove()方法在操作失败时会返回null,而Hashtable的put()和remove()方法会抛出异常。 5. 使用场景:因为HashMap是线程不安全的,所以它更适合在单线程环境中使用,而Hashtable则更适合在多线程环境中使用。 ### 回答2: HashMapHashtableJava中的两种常用的集合类,它们都实现了Map接口,用于存储键值对。 首先,HashMapHashtable的主要区别在于线程安全性。Hashtable是线程安全的,而HashMap不是。因为Hashtable的所有方法都是同步的,可以在多线程环境下使用,但是这也导致了效率较低。而HashMap则不提供同步,如果在多线程环境下使用需要自己进行同步处理。 其次,HashMap允许将null作为键和值,而Hashtable不允许。这是因为Hashtable使用了Enumeration迭代器,而null值会导致NullPointerException。 另外,HashMap是非线程安全的,但是在大多数情况下比Hashtable效率更高,因为Hashtable需要额外的同步操作。在单线程环境下,推荐使用HashMap,而在多线程环境下需要线程安全的情况下可以使用Hashtable或者ConcurrentHashMap。 此外,HashMap的键对象可以是非线程安全的,但是Hashtable的键对象必须是线程安全的。这是因为Hashtable在计算键的散列值时,会直接使用键对象的hashCode方法,而HashMap则会使用键对象的hashCode方法计算散列值,再通过散列值计算得到数组的下标位置。 综上所述,HashMapHashtable区别主要体现在线程安全性和对null值的处理上。在单线程环境下选择HashMap,在多线程环境下选择线程安全的Hashtable或者ConcurrentHashMap

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈永佳

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值