java各种map

java为数据结构映射定义了一个接口java.util.Map,它分别有四个实现分别是(不只这些)

  • HashMap
  • HashTable
  • LinkedHashMap
  • TreeMap

主要用于存储键值对,根据键得到值,因此不允许键重复(重复就覆盖了),但是允许值重复

Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。

HashTable

Hashtable与 HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。

和hashmap的区别

底层数据结构不同:jdk1.7底层都是数组+链表,但jdk1.8 HashMap加入了红黑树
Hashtable 是不允许键或值为 null 的,HashMap 的键值则都可以为 null。
添加key-value的hash值算法不同:HashMap添加元素时,是使用自定义的哈希算法,而HashTable是直接采用key的hashCode()
实现方式不同:Hashtable 继承的是 Dictionary类,而 HashMap 继承的是 AbstractMap 类。
初始化容量不同:HashMap 的初始容量为:16,Hashtable 初始容量为:11,两者的负载因子默认都是:0.75。
扩容机制不同:当已用容量>总容量 * 负载因子时,HashMap 扩容规则为当前容量翻倍,Hashtable 扩容规则为当前容量翻倍 +1。
支持的遍历种类不同:HashMap只支持Iterator遍历,而HashTable支持Iterator和Enumeration两种方式遍历
迭代器不同:HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。而Hashtable 则不会。
部分API不同:HashMap不支持contains(Object value)方法,没有重写toString()方法,而HashTable支持contains(Object value)方法,而且重写了toString()方法
同步性不同: Hashtable是同步(synchronized)的,适用于多线程环境,
而hashmap不是同步的,适用于单线程环境。多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。

LinkedHashMap

LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

LinkedHashMap继承自HashMap它的多种操作都是记录在HashMap操作基础上的.和Has和Map不同的是,LinkedHashMap维护了Entry的双向链表,保证了插入Entry中的顺序.这也是Linked的含义

原理

为了实现双向链表,LinkedHashMap中提供了如下的Entry:

    /**
     * LinkedHashMap中的node直接继承自HashMap中的Node。并且增加了双向的指针
     */
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

可以说LinkedHashMap=HashMap+双向链表

  /**
     * 头指针,指向第一个node
     */
    transient LinkedHashMap.Entry<K,V> head;

    /**
     * 尾指针,指向最后一个node
     */
    transient LinkedHashMap.Entry<K,V> tail;

    /**
     * 一个条件变量,它控制了是否在get操作后需要将新的get的节点重新放到链表的尾部
     * LinkedHashMap可以维持了插入的顺序,但是这个顺序不是不变的,可以被get操作打乱。
     *
     * @serial
     */
    final boolean accessOrder;

其他的元素就是直接继承HashMap中的。

总结:LinkedHashMap就是将hashmap中的node维护成了一个双向链表.只要搞懂了hashmap就可以很容易搞懂LinkedHashMap

(58条消息) 超详细LinkedHashMap解析_求offer的菜鸡的博客-CSDN博客_linkedhashmap

(linkedhashmap保存的是插入时的顺序,treemap是排序后的)

TreeMap

TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点。

红黑树的插入、删除、遍历时间复杂度都为O(lgN),所以性能上低于哈希表。但是哈希表无法提供键值对的有序输出,红黑树因为是排序插入的,可以按照键的值的大小有序输出。

Last modification:November 3, 2022
如果觉得我的文章对你有用,请随意赞赏