JavaSE——类型安全的容器介绍之Map

Java集合框架详解
本文深入探讨Java中的集合框架,包括List、Set、Queue和Map的基本概念与应用。特别聚焦于Map的各种实现,如HashMap、LinkedHashMap、TreeMap、WeakHashMap和ConcurrentHashMap,详细解析它们的特性、使用场景及内部工作原理。

我们从学习c语言开始,就已经开始使用“数组“,数组是保存一组对象的最有效的方式,如果你想保存一组基本的数据类型,也推荐这种方式,但是数组具有固定的尺寸,而在一般情况中,我们在写代码的时候,不知道需要多少个对象,或者 是否需要更复杂的方式来存储对象,因此,数组尺寸固定这样一个条件就过于受限了。在Java中,有一套相当完整的容器来解决这个问题,其中基本的类型是List、Set、Queue和Map,这些对象称为集合类,但是由于Java的类库中使用了Collection这个名字来指代类库的一个特殊子集,所以,我们常用“容器”来称呼他们

1、基本概念

1)Collection:一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序来保存元素,Set不能有重复的元素
在这里插入图片描述
2)Map:一组成对的“键值对”对象,允许用键来查找值

1.2、Map和Collection的区别

  • Map 存储的是键值对形式的元素,键唯一,值可以重复。
  • Collection 存储的是单列元素,子接口Set元素唯一,子接口List元素可重复。
  • Map集合的数据结构值针对键有效,跟值无关,Collection集合的数据结构是针对元素有效

2、Map(映射)理解

在这里插入图片描述

2.1、Map实现

HashMapMap基于散列表的实现(取代了HashTable)。插入和查询“键值对”的开销是固定的,可以通过构造器设置容量和负载因子,以调整容器的性能
LinkedHashMap类似于HashMap,但是迭代器遍历他时,取得“键值对”的顺序是其插入次序,或者是最近最少使用的次序,只比HashMap慢一点,而在迭代器访问时反应更快,因为它使用链表维护内部次序
TreeMap基于红黑树的实现,查看“键”或“键值对”时,他们会被排序。TreeMap的特点在于,所得到的的结果都是经过排序的。TreeMap是唯一的带有subMap()方法的Map,他可以返回一个子树
WeakHashMap弱键映射,允许释放映射所指向的对象,这是为解决某类特殊问题而设计的,如果映射之外没有引用某个“键”,则此键可以被垃圾收集器回收
ConCurrentHashMap一种线程安全的Map,不涉及同步加锁

2.2、Map的常用方法

  • 插入(put、putAll())
  • 删除(remove())
  • 获取(entrySet()、get()、keySet()、size()、values())
  • 判断(containsKey()、containsValue()、equals()、isEmpty())
  • 清除(clear())
  • 替换(replace(),replace(K key, V oldValue, V newValue)

打印类型

//打印Map类型
public static void test(Map<Integer,String> map){
        System.out.println(map.getClass().getSimpleName());
    }
    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

插入

//插入方法
 public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());
    }
    public static void test(Map<Integer,String> map){
        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

删除

//删除方法
 public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());
    }
    public static void test(Map<Integer,String> map){
        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        map.remove(2);
        printKeys(map);
    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

获取

//获取方法
public static void printKeys(Map<Integer,String > map){
//主要在这里
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());
        System.out.println("values="+map.values());
        System.out.println("get="+map.get(1));
        System.out.println("entrySet="+map.entrySet());
    }
    public static void test(Map<Integer,String> map){
        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);

    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

判断

//判断比较containsKey()、containsValue(),一个比较“键”,一个比较“值”
public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());

    }
    public static void test(Map<Integer,String> map){
        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        System.out.println(map.containsKey(3));
        System.out.println(map.containsKey(6));
        System.out.println(map.containsValue("!!!"));
        System.out.println(map.containsValue("..."));
    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

//equals用来比较两个map是否相等
public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());

    }
    public static void test(Map<Integer,String> map){
        Map<Integer,String> map2=new HashMap<>();
        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        System.out.println(map.equals(map2));
        map2.put(1,"hello");
        map2.put(2,"world");
        map2.put(3,"!!!");
        System.out.println(map.equals(map2));

    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

//判空
public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());

    }
    public static void test(Map<Integer,String> map){

        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        System.out.println(map.isEmpty());
        map.remove(1,"hello");
        map.remove(2,"world");
        map.remove(3,"!!!");
        printKeys(map);
        System.out.println(map.isEmpty());


    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

清空

//清空
public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());

    }
    public static void test(Map<Integer,String> map){

        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        map.clear();
        printKeys(map);


    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

代替

public static void printKeys(Map<Integer,String > map){
        System.out.println("size="+map.size());
        System.out.println("Keys="+map.keySet());
        System.out.println("value="+map.values());

    }
    public static void test(Map<Integer,String> map){

        System.out.println(map.getClass().getSimpleName());
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"!!!");
        printKeys(map);
        map.replace(1,"2");
        map.replace(4,"2");
        printKeys(map);
    }

    public static void main(String[] args) {
        test(new HashMap<Integer, String>());
        test(new LinkedHashMap<Integer, String>());
    }

在这里插入图片描述

3、HashMap的简单介绍

3.1、HashMap内部结构

在这里插入图片描述
HashMap在JDK1.8之后是基于哈希表和红黑树实现的,JDK1.8之前只基于哈希表

3.2、基本映射操作

HashMap也被称为散列映射,散列映射比较函数只能作用于键,与键关联的值不能进行散列或比较
TreeMap被称为树散列,树散列用键的整体顺序对元素进行排序,并将其组织成搜索树
Map中的方法,HashMap全都有

3.3、HashMap源码解析

内部属性

负载因子:final float loadFactor(默认为0.75f)
实际容量:int threshold= loadFactor*tab.length;
树化阈值:int TREEIFY_THRESHOLD=8
解除树化阈值:int UNTREEIFY_THRESHOLD=6

HashMap也采用懒加载策略,第一次put时初始化哈希表
树化逻辑:索引下标对应的链表长度达到阈值8,并且当前哈希表长度达到64才会树化,否则只是调用resize方法进行哈希表扩容,扩容为原先数组的2倍
负载因子过大会导致哈希冲突明显增加,节省内存
负载因子过小会导致哈希表频繁冲突,内存利用率低

JDK1.8为何要引入红黑树?

当链表长度过长,会将哈希表查找的时间复杂度退化为O(n)
树化保证即便在哈希冲突严重时,查找时间复杂度也为O(logn)
当红黑树节点个数在扩容或删除元素时减少为6以下,在下次resize过程中会将红黑树退化为链表

4、TreeMap

TreeMap是SortedMap唯一实现,可以确保键处于排序状态,这使得它具有额外的功能,这些功能由SortedMap接口中的下列方法提供:

方法功能
Comparator comparator()返回当前 Map使用的Comparator,或者返回null,表示以自然方式排序
T firstKey()返回Map中的第一个键
T LastKey()返回Map中的最末一个键
Sorted subMap(formKey,toKey)生成Map的子集,范围由fromKey(包含)到toKey(不包含)的键确定
Sorted headMap(toKey)生成此Map的子集,由键小于toKey的所有键值对组成
Sorted tailMap(fromKey)生成此Map的子集,由键大于fromKey的所有键值对组成

TreeMap中键值对都是按键的次序排列的,TreeMap中的次序是有意义的,因此“位置”的概念才有意义,所以才能取得第一个和最后一个元素,并且可以提取Map的子集

5、LinkedHashMap

在这里插入图片描述LinkedHashMap用来记住插入顺序,这样就可以避免在散列表中的项从表面上看是随机排列的,如上图,当条目插入到表中,,就会并入双向链表中

6、equals

HashMap使用equals( )判断当前的键是否与表中存在的键相同,正确的equals( )必须满足下列5个条件:

性质含义
自反性对于任意x,x.equals(x)一定返回true
对称性对任意的x和y,如果x.equals(y)返回true,那么,y.equals(x)也返回true
传递性对于任意的x、y、z,如果x.equals(y)返回true,y.equals(z)也返回true,那么,x.equals(z)一定返回true
一致性对于任意的x,y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一致是true,要么一致是flase
null对任何不是null的x,x.equals(null)一定返回flase

hashCode和equals的关系
hashCode:取得任意一个对象的哈希码
equals:比较两个对象是否相等
hashCode返回值相等的两个对象,equals不一定相等(x与f(x)的关系)
equals返回值相等的两个对象,hashCode一定相等

标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值