2.Hashtable

Hashtable,顾名思义,哈希表,本来是已经被淘汰的内容,但在某一版本的Java将其实现了Map接口,因此也成为常用的集合类,但是hashtable由于和hashmap十分相似,因此据说也成为“面试经典题”。由于两者的区别网上实在太多太多,我就不自己在摸索了直接拷贝过来用于借鉴:

  • HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行。
  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 提供了ConcurrentHashMap,它解决了HashMap的线程不安全的问题和Hashtable效率低的问题。
  • 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
  • 还有一点,算不上区别吧,HashMap是继承实现了Map接口的虚类AbstractMap,而Hashtable继承Dictionary类,并且实现Map接口。

至于前三点可以说是最多被提及的,当然HashMap可以通过下面的语句进行同步:

Map m = Collections.synchronizeMap(hashMap);

 然后我们来深入讨论一下其他的的几个区别

  • 是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不仅仅是fail-fast的,还使用了Enumeration的方式。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

前面咱们已经讨论过HashMap的一些遍历方式,可以确定的是HashMap的遍历方式Hashtable都有,但是Hashtable在此基础上还有Enumeration的方式,我们直接以实例来展示:

    public static void main(String [] args)
    {
        Hashtable ht = new Hashtable<String, Integer>();
        for(int i=100;i<105;i++)
        {
            ht.put(String.valueOf(i)+"th",i);
        }
        System.out.println(ht);
        Enumeration enu = ht.keys();
        while(enu.hasMoreElements()) {
            System.out.println(enu.nextElement());
        }

    }

结果如下:

{102th=102, 104th=104, 101th=101, 103th=103, 100th=100}
102th
104th
101th
103th
100th

也证明Hashtable或者HashMap不是所谓的有序排列。keys()遍历Hashtable的键,同样的elements()也会遍历Hashtable的值。

为了内容的延续性我们放到后面来讲fail-fast机制。接下来还是看两个集合的区别。

  •  扩容机制不同

 在此之前,先看一下Hashtable的构造函数:

    public Hashtable(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);

        if (initialCapacity==0)
            initialCapacity = 1;
        this.loadFactor = loadFactor;
        table = new Entry<?,?>[initialCapacity];
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    }

    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    public Hashtable() {
        this(11, 0.75f);
    }

    public Hashtable(Map<? extends K, ? extends V> t) {
        this(Math.max(2*t.size(), 11), 0.75f);
        putAll(t);
    }
Hashtable Construction Functions

相关文章: