Hashtable,HashMap,TreeMap的区别

本文深入探讨了Java集合类库中的Hashtable与HashMap的区别,包括它们的线程安全性、对null的支持、性能特点及内部实现机制。同时,还介绍了基于红黑树实现的TreeMap,详细解释了其排序方式及时间复杂度。

Hashtable

Hashtable是java集合类库早期的一个实现(类名Hashtable不是HashTable),线程同步,不支持null键和值,由于同步,性能较差。

	//synchronized同步
    public synchronized V put(K key, V value) {
       // Make sure the value is not null
       //值不能为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];
       //值不能为null
       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;
   

HashMap

HashMap是最常用的集合类之一,底层实现由数据和链表构成。
HashMap线程不同步,可支持null键和值。
HashMap默认容量为16,且要求容量一定为2的整数次幂,当元素增长到需扩容时,默认增加长度一倍
数据中存储的是桶(bucket)后面跟着存储键值对的链表,HashMap通过计算需存储元素的哈希值,决定该元素存储在数据的哪个位置上。相同哈希值的键值对会存在数据的同一个位置上,按链表形式存储。
当相同哈希值的元素个数超过设定的阈值(TREEIFY_THRESHOLD,默认为8)时,则会由链表自动转成红黑
树形式存储。

存储格式:
在这里插入图片描述

TreeMap

TreeMap是一种有序的,基于红黑树实现的Map。常用的put,get,remove时间复杂度O(log(n)),操作速度较慢。元素排序方式,由其成员变量comparator决定:

    /**
     * The comparator used to maintain order in this tree map, or
     * null if it uses the natural ordering of its keys.
     *
     * @serial
     */
    private final Comparator<? super K> comparator;

可以在TreeMap初始化时,传入自定义的Comparator,以满足自己的排序需要。

  public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
HashMapHashtableTreeMap都是Java中用于存储键值对的集合类,但它们在多个方面存在区别: 1. **同步性**:HashMap不是同步的,任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致;而Hashtable是同步的,同一时刻只能有一个线程对其进行写操作,能保证线程安全。如果需要对HashMap进行同步,可以使用Collections的synchronizedMap方法或使用ConcurrentHashMap类[^1][^2]。 2. **键和值的支持**:HashMap支持null键和null值;Hashtable不允许null键和null值,否则会抛出NullPointerException;TreeMap不允许键为null,但值可以为null,如果插入null键会抛出NullPointerException [^1][^5]。 3. **性能**:通常情况下,HashMap进行put和get方法操作时可以达到常数时间的性能,是大部分利用键值对存取场景的首选;Hashtable由于是同步的,性能相对较低;TreeMap基于红黑树实现,put和get操作的时间复杂度是O(log n),适用于需要对键进行排序的场景 [^1]。 4. **迭代器**:HashMap使用Iterator进行迭代,并且其迭代器是fail-fast的,当有其它线程改变了HashMap的结构(增加或者移除元素),可能会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出此异常;Hashtable使用Enumeration进行迭代,不是fail-fast的 [^3][^4]。 5. **哈希数组默认大小和扩容方式**:Hashtable中hash数组默认大小是11,增加的方式是old * 2 + 1;HashMap中hash数组的默认大小是16,而且一定是2的指数 [^3]。 6. **排序**:HashMap不保证元素的顺序;Hashtable也不保证元素的顺序;TreeMap会根据键的自然顺序或指定的比较器对元素进行排序 [^1]。 以下是简单的代码示例: ```java import java.util.HashMap; import java.util.Hashtable; import java.util.TreeMap; import java.util.Map; public class MapDifferenceExample { public static void main(String[] args) { // HashMap示例 Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("One", 1); hashMap.put(null, 3); hashMap.put("Four", null); System.out.println("HashMap: " + hashMap); // Hashtable示例 Map<String, Integer> hashtable = new Hashtable<>(); hashtable.put("One", 1); // hashtable.put(null, 3); // 会抛出NullPointerException // hashtable.put("Four", null); // 会抛出NullPointerException System.out.println("Hashtable: " + hashtable); // TreeMap示例 Map<String, Integer> treeMap = new TreeMap<>(); treeMap.put("One", 1); // treeMap.put(null, 3); // 会抛出NullPointerException treeMap.put("Four", null); System.out.println("TreeMap: " + treeMap); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值