• Java回顾-集合-Map-HashMap/LinkedHashMap/TreeSet/Properties


    一、Map概述

    Map:双列数据,存储key-value对的数据

            -HashMap:Map的主要实现类,线程不安全,效率高,可存储null的key和value

            -LinkedHashMap:保证遍历元素时,可以按照添加的顺序实现遍历

            -TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,TreeMap中添加的key必须是同一个类创建的对象,因为要用key进行自然排序定制排序

            -Hashtable:古老的实现类,线程安全,效率低,不能存储null的key和value

                    -Properties:常用来处理配置文件,key、value都是String型。

    结构:

    -HashMap的底层:数组+链表+红黑树(jdk8+)

            -Map中的key:无序,不可重复,使用Set存储所有的key ,key所在类要重写equals()hashCode() (以HashMap为例)

            -Map中的value:无序,可重复,使用Collection存储所有的value,value所在类要重写equals()

            -Map中的entry:无序,不可重复,使用Set存储所有的entry,key-value构成一个Entry对象

     二、常用方法

    添加、删除、修改操作

            Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中

            void putAll(Map m):将m中的所有key-value对存放到当前map中

            Object remove(Object key):移除指定key的key-value对,并返回value

            void clear():清空当前map中的所有数据

    元素查询的操作

            Object get(Object key):获取指定key对应的value

            boolean containsKey(Object key):是否包含指定的key

            boolean containsValue(Object value):是否包含指定的value

            int size():返回map中key-value对的个数

            boolean isEmpty():判断当前map是否为空

            boolean equals(Object obj):判断当前map和参数对象obj是否相等

    元视图操作的方法

            Set keySet():返回所有key构成的Set集合

            Collection values():返回所有value构成的Collection集合

            Set entrySet():返回所有key-value对构成的Set集合

    三、HashMap

    1.介绍

            HashMap是 Map 接口使用频率最高的实现类。

            允许使用null键和null值,与HashSet一样,不保证映射的顺序

            HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true, hashCode 值也相等。

            HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

     

     2.源码简析


            以jdk7为例,在实例化以后,底层创建了长度是16的一维数组Entry[] table。
            put操作
           首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置:
           1.如果此位置上的数据为空,此时的key1-value1添加成功。 ----情况1
            2.如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个多个数据的哈希值
                  2.1如果key1的哈希值已存在数据的哈希值都不相同,key1-value1添加成功。---情况2
                  2.2如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:

                  调用key1所在类的equals(key2)方法,比较:
                            2.2.1如果equals()返回false:此时key1-value1添加成功。----情况3
                            2.2.2如果equals()返回true:使用value1替换value2。
         *补充:关于情况2情况3:此时key1-value1和原来的数据以链表的方式存储。在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有的数据复制过来。

             jdk8 相较于jdk7在底层实现方面的不同
            1. new HashMap():底层没有创建一个长度为16的数组,相当于懒汉式
            2. jdk 8底层的数组是:Node[],而非Entry[]
            3. 首次调用put()方法时,底层创建长度为16的数组
            4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树
            4.1 形成链表时,七上八下(jdk7:的元素指向的元素。jdk8:的元素指向的元素)
            4.2 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所有数据改为使用红黑树存储。

    一些重要参数:
           DEFAULT_INITIAL_CAPACITY : HashMap的默认容量16
           DEFAULT_LOAD_FACTOR:HashMap的默认加载因子0.75,过了这个阈值就扩容
           threshold:扩容的临界值,=容量*填充因子:16 * 0.75 => 12
           TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
           MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64

    四、LinkedHashMap

            源码节选

    1. static class Entry<K,V> extends HashMap.Node<K,V> {
    2.              Entry<K,V> before, after;//能够记录添加的元素的先后顺序
    3.              Entry(int hash, K key, V value, Node<K,V> next) {
    4.                 super(hash, key, value, next);
    5.              }
    6.          } 

          相对于HashMap多了两个指向前驱后继元素的指针。与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序迭代顺序与 Key-Value 对的插入顺序一致。

    五、TreeMap

            TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。 TreeMap 可以保证所有的 Key-Value 对处于有序状态。

            TreeSet底层使用红黑树结构存储数据

            TreeMap 的 Key 的排序:

                    自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有 的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

                    定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口

    1. TreeMap map = new TreeMap(new Comparator() {
    2. @Override
    3. public int compare(Object o1, Object o2) {
    4. if(o1 instanceof User && o2 instanceof User){
    5. User u1 = (User)o1;
    6. User u2 = (User)o2;
    7. return Integer.compare(u1.getAge(),u2.getAge());
    8. }
    9. throw new RuntimeException("输入的类型不匹配!");
    10. }
    11. });

            TreeMap判断两个key相等的标准:两个key通过compareTo()方法或 者compare()方法返回0。

    六、Properties

            Properties 类是 Hashtable 子类,该对象用于处理属性文件

            由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key 和 value 都是字符串类型

            存取数据时,建议使用setProperty(String key,String value)方法和 getProperty(String key)方法

  • 相关阅读:
    C语言中strcpy()
    代码随想录第三十天|无重叠区间| 划分字母区间| 合并区间
    【以太网硬件十四】以太网的MAC是干什么的?
    设计原则之【依赖反转原则】
    PS-HDR图像编辑与应用
    百度安全X盈科全球数据合规服务中心:推进数据安全及合规智能化创新领域深化合作
    SpringCloud自定义负载均衡策略--LoadBalancer
    2022-06-28 网工进阶(十三)IS-IS-路由过滤、路由汇总、认证、影响ISIS邻居关系建立的因素、其他命令和特性
    电力系统潮流分析(Matlab代码实现)
    Node.JS入门(day01)
  • 原文地址:https://blog.csdn.net/weixin_62427168/article/details/125470878