Java集合(三)

目录

Map接口

Map接口常用方法

 Map实现类之一:HashMap

HashMap的存储结构

HashMap底层实现原理(以jdk7为例)

jdk8相较于jdk7在底层实现方面的不同

HashMap源码中的重要常量

HashMap何时进行扩容

Map实现类之二:LinkedHashMap

Map实现类之三:TreeMap

Map实现类之四:Hashtable

Map实现类之五:Properties

HashMap、LinkedHashMap、TreeMap、Hashtable、Properties区别


Map接口

Map与Collection并列存在。用于保存具有映射关系的数据:key-value

Map 中的 key 和 value 都可以是任何引用类型的数据

Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法

常用String类作为Map的“键”

key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到 唯一的、确定的 value

Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和 Properties。其中,HashMap是 Map 接口使用频率最高的实现类

Map接口常用方法

添加、删除、修改操作:

 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(先调用HashCode(),equals()

 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集合 

import org.junit.Test;

import java.util.*;

/**
 * @author light
 * @Description   Map接口常用方法
 * @create 2023-01-19 15:41
 */
public class MapTest {
    @Test
    public void test1(){
        /*
         *  添加、删除、修改操作:
         *  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中的所有数据
         */

        //添加
        Map map=new HashMap();
        map.put("AA",123);
        map.put("BB",345);
        map.put("CC",789);
        map.put("DD",234);
        map.put("EE",567);
        //修改
        map.put("AA","abc");
        System.out.println(map);

        Map map1=new HashMap();
        map1.put("ff","qwe");
        map1.put("KK",5667);

        map.putAll(map1);

        System.out.println(map);

        //remove(object key)
        Object remove = map.remove("K");
        System.out.println(remove);
        System.out.println(map);

        //clear()
        map.clear();
        System.out.println(map.size());


    }

    @Test
    public void test2(){

        /*
         *  元素查询的操作:
         *  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是否相等
         */
        Map map=new HashMap();
        map.put("AA",123);
        map.put("BB",345);
        map.put("CC",789);
        map.put("DD",234);
        map.put("EE",567);

        System.out.println(map.get("AA"));

    }

    @Test
      public void test3(){
        /*
         *  元视图操作的方法:(遍历)
         *  Set keySet():返回所有key构成的Set集合
         *  Collection values():返回所有value构成的Collection集合
         *  Set entrySet():返回所有key-value对构成的Set集合
         *
         */

        Map map=new HashMap();
        map.put("AA",123);
        map.put("BB",345);
        map.put("CC",789);
        map.put("DD",234);
        map.put("EE",567);

        //遍历所有key集:keySet()
        Set set=map.keySet();

        Iterator iterator = set.iterator();

        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("************************");

        //遍历所有value集
        Collection coll=map.values();

//        Iterator iterator1 = coll.iterator();
//
//        while(iterator1.hasNext()){
//            System.out.println(iterator1.next());
//        }

        for(Object col:coll){
            System.out.println(col);
        }

        System.out.println("************************");

        //遍历所有key-value集

        Set entry=map.entrySet();

        //方式一:enytrySet()
        Iterator iterator2 = entry.iterator();

        while (iterator2.hasNext()){

//            System.out.println(iterator2.next());
            Object obj = iterator2.next();
            Map.Entry e=(Map.Entry) obj;
            System.out.println(e.getKey() + "------>" + e.getValue());
            }
        System.out.println("************************");

        //方式二:

        Set setKey=map.keySet();//返回所有key构成的Set集合
        Iterator iterator1 = setKey.iterator();
        while(iterator1.hasNext()){
            Object next = iterator1.next();
            Object o = map.get(next);
            System.out.println(next+ "==========" +o);
        }
    }
}

 Map实现类之一:HashMap

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

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

所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写: equals()和hashCode()

所有的value构成的集合是Collection:无序的、可以重复的。所以,value所在的类要重写:equals()

一个key-value构成一个entry

所有的entry构成的集合是Set:无序的、不可重复的

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

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

HashMap的存储结构

JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)

JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。

HashMap底层实现原理(以jdk7为例)

                                HashMap map=new HashMap();

在实例化后,底层创建了长度为16的一维数组 Entry[] table

                                ......(可能已经执行了许多put()操作)

                                map.put(key,value);

首先,调用key所在类的hashCode()计算出key的哈希值,此哈希值在经过某种算法之后得到了Entry数组在内存中的位置;

        1)如果此位置上的数为空,则此时key-value添加成功(情况一

        2)如果此位之上的数不为空,则意味着此位之上已经存在一个或多个数据(以链表形式存在),比较key和已经存在的一个或多个数据的哈希值:

                --2.1如果key的哈希值和已经存在的数据的哈希值不同,则此时key-value添加成功(情况二

                --2.2如果key的哈希值和已经存在的数据的哈希值相同,则调用key所在的类的equals()方法继续进行比较:

                        --2.2.1若equals()返回false,则添加不成功

                        --2.2.2若equals()返回true,则添加成功(情况三

补充:关于情况二和情况三:此时key-value和原来的数据以链表形式存储

在添加过程中,会涉及扩容问题,当超出临界值是(且要放得位置非空),默认扩容方式:扩容为原来的2倍,并将原数组数据复制过来

jdk8相较于jdk7在底层实现方面的不同

1.new HashMap():底层没有创建一个长度为16的数组

2.jdk8中底层数组是Node[],而非Entry[]

3.首次调用put()方法时,底层创建长度为16的数组

4.jdk7中底层结构只有数组+链表;jdk8中底层结构为数组+链表+红黑树;

当数组的某一个索引位置上的元素以链表形式存在的属于个数>8,且当当前数字组长度>64是,此时的索引位置上的数据改为红黑树存储

HashMap源码中的重要常量

HashMap何时进行扩容

当HashMap中的元素个数超过数组大小(数组总大小length,不是数组中个数 size)*loadFactor(填充因子)时 , 就 会 进 行 数 组 扩 容 , loadFactor 的默认 值 (DEFAULT_LOAD_FACTOR)为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小(DEFAULT_INITIAL_CAPACITY)为16,那么当HashMap中元素个数 超过16*0.75=12(这个值就是代码中的threshold值,也叫做临界值)的时候,就把 数组的大小扩展为 2*16=32,即扩大一倍

Map实现类之二:LinkedHashMap

LinkedHashMap 是 HashMap 的子类

在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序

与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代 顺序:迭代顺序与 Key-Value 对的插入顺序一致

LinkedHashMap底层使用结构与HashMap相同,因为LinkedHashMap继承于HashMap

区别:LinkedHashMap内部用Entry[]去替换Node[]

Map实现类之三:TreeMap

TreeMap存储 Key-Value对时,需要根据 key-value 对进行排序。

TreeMap 可以保证所有的 Key-Value 对处于有序状态。

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

TreeMap 的 Key 的排序:

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

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

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

Map实现类之四:Hashtable

Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap, Hashtable是线程安全的

Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。

与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value

与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序

Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。

Map实现类之五:Properties

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

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

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

HashMap、LinkedHashMap、TreeMap、Hashtable、Properties区别

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

LinkedHashMap:保证遍历Map元素时,可以按照添加元素的顺序实现遍历(在原有的HashMap底层结构上,添加了一对指针,指向前一个、后一个元素;对于频繁的遍历操作,此类执行效率高于HashMap)

TreeMap:保证按添加的key-value进行排序;此时考虑key的自然排序和定制排序;底层使用红黑树进行排序结构

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

Properties:常用来处理配置文件,可由和value都是String类型

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值