zoukankan      html  css  js  c++  java
  • HashMap和HashTable区别

    1,线程安全

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

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

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

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

    2,性能优劣

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

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

    3,NULL

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

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

    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();
    
            ...
    
    }     

    HashMap hash方法逻辑:

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

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

    4,实现方式

    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类。

    5,容量扩容

    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。

    6,迭代器

    HashMap中的Iterator迭代器是fail-fast的,而Hashtable的Enumerator不是fail-fast的。

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

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

    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的区别。

    
    
  • 相关阅读:
    JS控制SVG缩放+鼠标控制事件
    JS多线程之Web Worker
    通过Java调用Python脚本
    Cornerstone的使用
    SVN服务器的搭建
    Python 函数作用域
    RDD转换算子(transformantion)
    Spark RDD简介
    Django 外键
    Django 模型常用属性
  • 原文地址:https://www.cnblogs.com/fengyuduke/p/10608401.html
Copyright © 2011-2022 走看看