当前位置: 代码迷 >> 综合 >> 【JAVASE(8)】JAVASE学习--集合篇三(Map接口)
  详细解决方案

【JAVASE(8)】JAVASE学习--集合篇三(Map接口)

热度:42   发布时间:2023-11-30 15:06:12.0

Map接口:
     |---->Map接口:双列集合,用于存储一对一对(key-value)数据---->函数
            |---->HashMap:作为Map的主要实现类;线程不安全,效率高;存储null的key和value
                |---->LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
                                    原因是在原有的HashMap底层结构基础上,添加了一对指针,分别指向前一个元素和后一个元素
                                    对应频繁的遍历操作,此类执行效率高于HashMap
            |---->TreeMap:保证按照添加的key--value对,以key为主进行排序,实现排序遍历,此时考虑key的自然排序或定制排序
                            底层使用红黑树(排序二叉树的一种)
            |---->Hashtable:作为古老的实现类;线程安全,效率低;不能存储null的key和value
                |---->Properties:常用于处理配置文件。key和value都是String类型


    一、Map集合概述:
        java.util.Map<K,V>集合
            Map集合特点:
                1.map是双链集合,一个元素包含两个值(一个Key,一个Value)
                2.Map中元素,Key和Value的数据类型可以相同也可以不同;其中Key是不允许重复Value可以重复;而Key和Value是一一对应的

        HashMap底层:数组+链表(JDK7及其之前);数组+链表+红黑树(JDK8及其之后)
        CurrentHashMap与Hashtable的异同:CurrentHashMap实现了分段锁技术,不同线程可以分开访问不同的共享数据

    二、Map结构理解:
        Map中的Key:无序,不可重复,使用set存储---->要求key所在类重写equals()和hashCode()(以HashMap为例子)--(TreeMap则找自然排序和定值排序)
        Map中的Value:无序,可重复,使用Collection存储---->value所在类重写equals()
        一个键值对(key-value)构成了一个Entry对象
        Map中的Entry:无序,不可重复,使用set存储

    三、HashMap:
        1、HashMap的底层实现原理

 JKD7中{HashMap map=new HashMap()在是刻画以后,底层创建了长度是16的一位数组Entry[] table;map.put(key2,value2);map.put(key3,value3);map.put(key1,value1);首先,调用key1所在类的hashCode()计算key1的hash值,此hash值经过某种算法计算以后,得到在Entry数组中的存放位置{1.若此位置上的数据为空,此时key1-value1添加成功---->情况一2.若此位置上的数据为不空(意味着此位置上存在一个或多个数据(以链表的形式存在)),比较key1和已经存在的一个或多个数据的hash值{1.若key1的hash值与已经存在的数据的hash值均不同,此时key1-value1添加成功---->情况二2.若key1的hash值与已经存在的某一个数据(key7,value7)的hash值相同,继续比较:调用key1所在类的equals(key7)方法,比较:{1.若equals返回false:此时key1-value1添加成功---->情况三2.若equals返回true:使用value1替换相同key7的value7值}}}补充:关于情况二和情况三:此时key1-value1和原理的数据以链表的方式存储在不断的添加过程中,会涉及扩容问题,当超出临界值切要存放的位置非空时,则扩容。默认的扩容方式:扩容为原来的2倍,并将原有的数据复制过来
}JDK8中{基本框架沿用了JDK7的基本框架,不同之处在于:1.new HashMap()底层没有创建一个长度为16的数组2.在jdk8中底层的数组是Node[]而非Entry[]3.首次调用put()方法时,底层创建长度为16的数组4.jdk7底层结构只有:数组+链表;在jdk8后底层结构:数组+链表+红黑树当数组的某一个索引位置上的元素以链表的形式存在的数据个数大于8,且当前数组的长度大于64时,此索引位置上的所有数据改为使用红黑树存储,目的是便于查找
}

        2、java.util.HashMap<K,V>集合 implements Map<k,v>接口
            HashMap<K,V>集合
                1.HashMap底层是hash表;查询时特别快;
                    jdk1.8以前:数组+单向链表;
                    jdk1.8以后:数组+单向链表/红黑树(链表长度超过8);提高查询速度
                2.HashMap是一个无序的集合,存取元素顺序可能不同

        3、 HashMap存储自定义类型键值
            Map集合保证Key是唯一的:
                作为key元素,必须重写hashCode和equals方法,以保证key唯一
            value可以重复

        4、HashMap中的常量描述:

DEFAULT_INITIAL_CAPACITY:HashMap默认的容量,16MAXIMUM_CAPACITY:HasMap最大支持的容量,2^30DEFAULT_LOAD_FACTOR:HashMap默认的加载(负载)因子,默认0.75;决定了HashMap中的数据密度,加载因子越大数据密度越大,发生碰撞的机率越高。(碰撞:两个key不一样,将两个key放在了数组的同一索引位置上)TREEIFY_THRESHOLD:BUcket中链表长度大于该默认值,转化为红黑树默认值为8UNTREEIFY_THRESHOLD:BUcket中红黑树存储的Node小于该默认值,转化为链表MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量(当桶中Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY值,此时应该执行resize扩容操作这个MIN_TREEIFY_CAPACITY值的最少是REEIFY_THRESHOLD的4倍)默认值为64table:存储元素的数组,总是2的n此幂entrySet:存储具体元素的集size:HashMap中存储的键值对的数量modCount:HashMap扩容和结构改变的次数threshold:扩容的临界值,=容量*填充因子=12=16*0.75loadFactor:填充因子,

            注:HashMap在不满16时(其实是满12)扩容的原因是减少HashMap中的链表长度,为了尽可能减少链表长度,提高使用效率,故将加载
            因子DEFAULT_LOAD_FACTOR的值默认取0.75

    四、LinkedHashMap:
        1、LinkedHashMap的底层原理实现:(对于频繁的遍历,则可以使用LinkedHashMap替换HashMap)
            LinkedHashMap的底层使用的结构与HashMap相同,因为LinkedHashMap继承于HashMap;区别在于:LinkedHashMap内部提供了Entry,替换了HashMap中的Node
            在jdk8源码中

{java.util.linkedHashMap<K,v> extends HashMap<K,V>Map接口的hash表和链表实现,具有可预知的迭代顺序。底层原理:hash表+链表(记录元素顺序)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);}}
}

        2、HashSet底层是HashMap,HashSet中的值则是存放在了底层HashMap中的键存储位置,而底层HashMap中的值则存储的是静态对象,即HashSet存储数据,在底层用HashMap存储,底层的HashMap中的键数据就是HashSet存储数据,并且底层的HashMap中的键数据对应了同一个静态Object值。
            

        3、java.util.LinkedHashMap<K,V>集合 extends HashMap<k,v>集合
            LinkedHashMap特点:
                1.LinkedHashMap底层是hash表+链表(保证迭代的顺序)
                2.LinkedHashMap是一个有序集合,存取元素顺序一致    五、Map中定义的方法:
        1、增删改:

public V put(K key,V value)将指定键,指定值放到Map集合中返回值:v存储键值对的时候:key不重复,返回值v是null存储键值对的时候:key重复,会使用新的value替换map中重复的value,返回被替换的值value将指定的key-value添加到(或修改)当前map对象中void putAll(Map m);将m中的所有key-value对存放到当前map中Object remove(Object key);移除指定key的key-value对,并返回value,其中key不存在,v返回nullvoid clear();清空当前map中的所有数据,与map=null;不同,底层将size改为0,将tab[]数组中的内容置空

        2、查:

Object get(Object key);获取指定key对应的value,其中key不存在,v返回nullboolean containsKey(Object key);是否包含指定的keyboolean containsValue(Object value);是否包含指定的valueint size();返回map中key-value对的个数boolean isEmpty();判断当前map是否为空,底层拿int size();做判断boolean equals(Object obj);判断当前map和参数对象obj是否相等

        3、视图

Set keySet();返回所有key构成的Set集合Collection values();返回所有value构成的Collection集合Set entrySet();返回所有key-value对构成的Set集合注:entrySet集合中的元素都是entry

        4、Map的遍历:
            Map集合的第一种遍历方式:
                通过键找值的方式
                public Set<K> keySet()获取Map集合中所有键,存储到Set集合中

通过键到值的方法遍历map集合{集合中的键K[Set(K)]放到一个Set集合中[keySet()]{即:把map集合中所有的K放到Set集合中}在Set集合中利用迭代器/增强for遍历Set集合,可以得到每一个Key值再利用get(key)得到key对应的value值
}

            实现:
                    1.使用map集合中的keySet()方法,把map集合所有的key取出再放到set集合中;
                    2.遍历set集合获取map集合中的每一个key;
                    3.通过map集合中的get(key)方法,通过key找到value

            Map集合的第二种遍历方式:
                实现entry对象遍历
                    public Set<Map.Entry<K,V>> EntrySet()返回此映射当中包含映射关系的set视图,获取到Map集合中所有键值对对象的集合(Set集合){把map集合内部的多个entry对象取出来存储到一个set集合中}遍历set集合(获得set集合中的每一个entry对象)

{1.entry对象中的方法getKey()获取key;2.getValue()获取value}

                    Map.Entry<K,V>:在Map接口中有一个内部接口entry

{作用:当map集合一创建,则在map集合中创建一个entry对象,用于记录键与值(键值对对象,键与值映射关系)
}

                实现:
                    1.使用Map中的方法entrySet(),把map集合中多个entry对象取出存入set集合中
                    2.遍历set集合,取得每一个entry对象
                    3.实验entry对象中的方法getKey()和getValue()获得键与值


        小节常用方法:
            增:Object put(Object key,Object value);
            删:Object remove(Object key);
            改:Object put(Object key,Object value);
            查: Object get(Object key);
            长度:int size();
            遍历:Set keySet();/Collection values();/Set entrySet();

    六、TreeMap:
        向TreeMap中添加key-value,要求key必须是由同一个类创建对象,因为要按照key进行排序:自然排序,定制排序

    七、Hashtable:
        1、java.util.Hashtable<K,V>集合 implements Map<K,V>接口
            Hashtable底层也是一个hash表,是一个单线程同步安全的集合,速度慢
            HashMap底层是一个hash表,是一个多线程不同步不安全的集合,速度快

        2、HashMap集合(之前所学所有集合)均可以存储null值,null键;Hashtable不能存储null值null键

        3、Hashtable和vector集合应一样,在jdk1.2之后被更先进的集合(HashMap,ArrayList)取代

        4、Hashtable的子类properties依然仍被广泛使用

        5、properties集合是一个唯一和IO流相结合的集合
            Properties:常用于处理配置文件。key和value都是String类型


    八、JDK9新特性:
        List接口,Set接口,Map接口:里面增加了一个静态方法of,可以给集合一次性添加多个元素
        static <E> List<E>(E...elements)
        使用前提:
            当集合中存储的元素个数已经确定,不在改变时使用
        注意:
            1.of方法仅适用List接口,Set接口,Map接口,不适用于接口实现类
            2.of方法返回值是一个不能改变的集合,集合不再使用add,put方法添加元素,否则抛出异常
            3.set接口map接口在调用of方法时不能有重复元素否则会抛出异常

    九、小节数据结构:

栈:先进后出
队:先进先出数组:查询快,增删慢;在堆内存中频繁创建新数组,复制老数组中元素到新数组中,销毁老数组,效率低下链表:查询慢,增删快;单向链表【只有一条链子,不能保证元素顺序(存储元素和取出元素顺序可能不一致)】双向链表【有两条链子,有一条链子是专门记录元素顺序的,是一个有序的集合】

以上是本篇小节,不喜勿喷,感谢理解

相关链接:

【JAVASE(9)】JAVASE学习--泛型篇_lixxkv的博客-CSDN博客
【JAVASE(8)】JAVASE学习--集合篇二(Collection接口)_lixxkv的博客-CSDN博客

  相关解决方案