【JAVA入门】Day31 - 双列集合 —— Map 系列

news2024/11/13 11:01:00

【JAVA入门】Day31 - 双列集合 —— Map 系列


文章目录

  • 【JAVA入门】Day31 - 双列集合 —— Map 系列
    • 一、双列集合体系结构
    • 二、Map 的遍历方式
      • 2.1 键找值
      • 2.2 键值对遍历
      • 2.3 Lambda 表达式遍历键值对
    • 三、HashMap
      • 3.1 HashMap的创建
    • 四、LinkedHashMap
    • 五、TreeMap


        单列集合每次添加元素时,只能添加一个元素;但双列集合每次添加元素时,是添加一对元素,双列集合每次添加的一对元素,我们称为键值对(Entry)。一个键和一个值是对应的。
在这里插入图片描述
        要注意:键和值是一一对应的,每一个键只能找到自己对应的值。键不能重复,但是值是可以重复的。
        键 + 值这个整体我们称之为“键值对对象”,在 Java 中叫做“ Entry 对象”。

一、双列集合体系结构

在这里插入图片描述
        在双列集合中,Map 是顶级接口,它的所有功能可以被全部双列集合继承使用。
        Map 集合定义了很多方法,如下表。
在这里插入图片描述
        方法使用细节如下代码。

package Maps;

import java.util.HashMap;
import java.util.Map;

public class MapDemo1 {
    public static void main(String[] args) {
        //1.创建Map对象
        //Map是接口,要创建实现类对象进行多态
        Map<String, String> m = new HashMap<>();

        //2.添加键值对
        m.put("郭靖","黄蓉");
        m.put("喜羊羊","美羊羊");
        String value1 = m.put("开心超人","宅博士");
        //会覆盖上一行数据,添加时如果键不存在,直接添加该键值对,然后返回none
        // 如果键已存在,会覆盖原有键值对,然后将被覆盖的值返回
        String value2 =  m.put("开心超人","甜心超人");
        //返回值测试
        System.out.println(value1);
        System.out.println(value2);

        //打印集合
        System.out.println(m);          //{开心超人=宅博士, 郭靖=黄蓉, 喜羊羊=美羊羊}

        //3.根据键删除键值对,返回被删除的值
        /*String result = m.remove("郭靖");
        System.out.println(m);
        System.out.println(result);*/

        //4.清空集合
        //m.clear();
        //System.out.println(m);

        //5.判断是否包含
        boolean keyResult = m.containsKey("郭靖");
        boolean valueResult = m.containsValue("美羊羊");
        System.out.println(keyResult);
        System.out.println(valueResult);

        //6.判断集合是否为空
        boolean result = m.isEmpty();
        System.out.println(result);

        //7.size集合长度
        int size = m.size();
        System.out.println(size);
    }
}

二、Map 的遍历方式

        Map 集合有三种遍历方式,键找值、依次获取键值对、Lambda 表达式遍历。

2.1 键找值

在这里插入图片描述        可以创建一个键的单列集合,通过每一个元素调用 get 方法来找对应的值。

package Maps;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo2 {
    public static void main(String[] args) {
        //遍历方式1
        //1.创建Map集合对象
        Map<String, String> map = new HashMap<>();

        //2.添加元素
        map.put("喜羊羊","美羊羊");
        map.put("大大怪","小小怪");
        map.put("虹猫","蓝兔");

        //3.通过键找值
        //3.1 把键获取放入单列集合
        Set<String> keys = map.keySet();
        //3.2 遍历单列集合得到每一个键
        for (String key : keys) {
            //System.out.println(key);
            //3.3 利用键获取每一个值
            String value = map.get(key);
            System.out.println(key + " = " + value);
        }
    }
}

2.2 键值对遍历

        获取每一对键值对,然后调用 get 方法获取键和值。
在这里插入图片描述

package Maps;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo3 {
    public static void main(String[] args) {
        //遍历方式2
        //1.创建Map集合对象
        Map<String, String> map = new HashMap<>();

        //2.添加元素
        map.put("喜羊羊","美羊羊");
        map.put("大大怪","小小怪");
        map.put("虹猫","蓝兔");

        //3.通过键值对对象遍历
        //3.1 通过一个方法获取所有键值对对象,返回一个set集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //3.2 遍历entries集合找到所有键值对对象
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " = " + value);
        }

    }
}

2.3 Lambda 表达式遍历键值对

        利用Lambda表达式遍历集合。

package Maps;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class MapDemo4 {
    public static void main(String[] args) {
        //遍历方式3
        //1.创建Map集合对象
        Map<String, String> map = new HashMap<>();

        //2.添加元素
        map.put("鲁迅","这句话是我说的");
        map.put("曹操","不可能,绝对不可能");
        map.put("刘备","接着奏乐,接着舞");
        map.put("张飞","我一枪挑了大哥!");

        //3.利用lambda表达式进行遍历
/*  map.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String key, String value) {
                System.out.println(key + "=" + value);
            }
        });*/
        map.forEach((key, value) -> System.out.println(key + "=" + value));
    }
}

三、HashMap

        HashMap 是 Map 的一个实现类。
        HashMap 中无额外方法,直接使用 Map 中的方法即可。
        HashMap 的特点由键决定:无序、不重复、无索引。
        HashMap 和 HashSet 在底层都是哈希表实现的:数组 + 链表 + 红黑树。

3.1 HashMap的创建

        在存入数据时,HashMap 是以键为准的,和值无关。它会利用键计算出哈希值,存入哈希表中。
在这里插入图片描述
        如果碰到已经存放元素的位置,还是根据键的属性值来判断。
在这里插入图片描述
        如果新元素的键和旧元素一模一样,直接覆盖之。
在这里插入图片描述
        如果新元素的键和旧的不一样,直接挂在旧元素下面,形成链表。
在这里插入图片描述
        当链表的长度超过8 & 数组长度>=64时,链表自动转成红黑树。

        根据底层结构可知,HashMap 底层存储和值没有任何关系,其依赖 hashCode() 方法和 equals() 方法保证键的唯一,如果键存储的是自定义对象,一定要重写这两个方法;但如果值存储的是自定义对象,那就不需要重写,存储和值无关。

【练习1】存储自定义对象。
需求:键为学生,值为籍贯。同年龄,同姓名认为是同一个学生。

package Maps;

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo1 {
    public static void main(String[] args) {
        //1.创建HashMap对象
        HashMap<Student, String> hm = new HashMap<>();

        //2.三个学生对象
        Student s1 = new Student("zhangsan", 23);
        Student s2 = new Student("lisi", 24);
        Student s3 = new Student("wangwu", 25);
        Student s4 = new Student("wangwu", 25);

        //3.添加元素,Student是键,值是籍贯
        hm.put(s1, "江苏");
        hm.put(s2, "浙江");
        hm.put(s3, "胡建");
        hm.put(s4, "山东"); //覆盖了wangwu

        //4.遍历集合
        Set<Student> keys = hm.keySet();
        for (Student key : keys) {
            String value = hm.get(key);
            System.out.println(key + " = " + value);
        }

		Set<Map.Entry<Student, String>> entries = hm.entrySet();
        for (Map.Entry<Student, String> entry : entries) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }

        hm.forEach((key, value) -> System.out.println(key + " = " + value));
    }
}

【练习2】利用 Map 集合统计投票人数。
需求:某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是((A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

package Maps;

import java.util.*;

public class HashMapDemo2 {
    public static void main(String[] args) {
        /*
        景点   投票次数
         */

        //存四个景点
        String[] arr = {"A", "B", "C", "D"};
        //利用随机数模拟80个同学投票,并存储投票结果
        ArrayList<String> list = new ArrayList<>();
        Random r = new Random();
        for(int i = 0 ; i < 80; i++) {
            int index = r.nextInt(arr.length);
            list.add(arr[index]);
        }

        HashMap<String, Integer> hm = new HashMap<>();

        for (String name : list) {
            //判断当前景点是否在集合中存在
            if(hm.containsKey(name)) {
                //获取当前景点已经被投票的次数
                int count = hm.get(name);
                //次数加一
                count++;
                //把当前景点及次数再次添加入hm中,覆盖原数据
                hm.put(name, count);
            }else{
                //不存在
                //表示当前景点是第一次出现
                hm.put(name, 1);
            }
        }

        System.out.println(hm);

        //3.遍历求该集合中的最大值
        int max = 0;
        Set<Map.Entry<String, Integer>> entries = hm.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            if(entry.getValue() > max) {
                max = entry.getValue();
            }
        }

        //4.再次遍历,打印景点投票次数和最大值一样的景点
        for (Map.Entry<String, Integer> entry : entries) {
            if(entry.getValue() == max) {
                System.out.println(entry.getKey());
            }
        }
    }
}

四、LinkedHashMap

        LinkedHashMap 是 HashMap 的子类,它的特性由键决定:有序、不重复、无索引。
        这里的有序指的是保证存储和取出的元素顺序一致。它的底层和 LinkedHashSet 类似,每个键值对存入哈希表中,又额外添加了一条双链表来记录存储的顺序。
在这里插入图片描述
        在遍历时,会根据这个双链表的头结点依次遍历,和元素的存入顺序达成了一致。

package Maps;

import java.util.LinkedHashMap;

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        //1.创建集合
        LinkedHashMap<String, Integer> lhm  = new LinkedHashMap<>();

        //2.添加元素
        lhm.put("123", 1);
        lhm.put("123", 2);
        lhm.put("abc", 3);
        lhm.put("cad", 4);

        //3.打印看看是不是按存储顺序
        System.out.println(lhm);
    }
}

五、TreeMap

        TreeMap 和 TreeSet 底层原理一样,都是红黑树结构的。
        TreeMap 的特性由键决定:不重复、无索引、可排序。
        TreeMap 的排序是对键的排序,默认按照键的从小到大排序(字符串就是字典顺序),也可以按照自己规定的排序规则排序,规定方式和 TreeSet 别无二致。

  • 实现 Comparable 接口,指定比较规则。
  • 创建集合时传入 Comparator 比较器对象,指定比较规则。

【练习】 需求1:键:整数表示id,值:字符串表示商品名称,要求:按照id的升序排列、按照id的降序排列。

package Maps;

import java.util.Comparator;
import java.util.TreeMap;

public class TreeMapDemo {
    public static void main(String[] args) {
        /*
        需求1:键:整数表示id,值:字符串表示商品名称,要求:按照id的升序排列、按照id的降序排列
         */

        //1.创建集合对象
        TreeMap<Integer,String> tm = new TreeMap<>();

        //2.添加元素
        tm.put(1,"粤利粤");
        tm.put(4,"雷碧");
        tm.put(5,"可恰可乐");
        tm.put(2,"康帅傅");
        tm.put(3,"九个核桃");

        //3.打印集合
        //默认按照键的升序进行排列
        System.out.println(tm);

        //按照id降序排列
        TreeMap<Integer,String> tm1 = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        tm1.put(1,"粤利粤");
        tm1.put(4,"雷碧");
        tm1.put(5,"可恰可乐");
        tm1.put(2,"康帅傅");
        tm1.put(3,"九个核桃");

        System.out.println(tm1);
    }
}

【练习】 需求2:键:学生对象,值:籍贯,要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人。

package Maps;

import java.util.Objects;

public class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public int compareTo(Student o) {
        //按年龄升序
        int i = this.getAge() - o.getAge();
        //年龄一样按姓名字母顺序
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        //姓名年龄都一样视为同一个人,TreeSet要添加的元素已经存在,就不存了
        return i;
    }
}

        Student 类实现 Comparable 接口,重写 compareTo() 方法。

package Maps;

import java.util.TreeMap;

public class TreeSetDemo5 {
    public static void main(String[] args) {
        //1.创建集合
        TreeMap<Student,String> tm = new TreeMap<>();

        //2.创建学生对象
        Student s1 = new Student("zhangsan", 23);
        Student s2 = new Student("lisi", 24);
        Student s3 = new Student("wangwu", 25);

        //3.添加学生姓名,籍贯键值对
        tm.put(s1,"福建");
        tm.put(s2,"湖南");
        tm.put(s3,"江苏");

        //4.重写了学生类的排序,这里直接打印即可
        System.out.println(tm);         //{Student{name='zhangsan', age=23}=福建, Student{name='lisi', age=24}=湖南, Student{name='wangwu', age=25}=江苏}
    }
}

【练习3】统计"aababcabcdabcde"每个字符出现次数,并按照以下格式输出:
a(5)b(4)c(3)d(2)e(1)

package Maps;

import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.function.BiConsumer;

public class TreeMapDemo6 {
    public static void main(String[] args) {
         //1.定义字符串
         String str = "aababcabcdabcde";

         //2.创建集合
         TreeMap<Character,Integer> tm = new TreeMap<>();

         //3.遍历字符串得到里面的每一个字符
         for(int i = 0; i < str.length(); i++) {
             char c = str.charAt(i);
             //如果字符没在tm中出现过,就说明其是第一次出现,就put c, 1,否则取出其count,然后++,再覆盖
             if(tm.containsKey(c)) {
                 int count = tm.get(c);
                 count++;
                 tm.put(c, count);
             }else{
                 tm.put(c, 1);
             }
         }

        //System.out.println(tm);

        //4.利用StringBuilder添加字符串按照指定格式拼接
        StringBuilder sb = new StringBuilder();
        tm.forEach((key,value) -> {
            sb.append(key).append("(").append(value).append(")");
        });

        System.out.println(sb);

        5.利用StringJoiner添加字符串按照指定格式拼接
        StringJoiner sj = new StringJoiner("");
        //sj只能add字符串,所以要把key和value后面都加一个"",把它变成字符串形式
        Set<Map.Entry<Character, Integer>> entries = tm.entrySet();
        for (Map.Entry<Character, Integer> entry : entries) {
            sj.add(entry.getKey() + "").add("(").add(entry.getValue() + "").add(")");
        }

        System.out.println(sj);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2106593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Excel使用VLOOKUP公式匹配不出正确公式,返回#N/A

问题&#xff1a; Excel使用VLOOKUP公式匹配不出正确公式&#xff0c;返回#N/A 原因&#xff1a; 原数据和匹配的数据格式不一致 解决办法&#xff1a; 把格式都设置为文本。 例如添加一列&#xff0c;输入英文符号&#xff0c;然后把数据源拼接起来&#xff0c;转换为文…

3招解决苹果手机qq图片恢复问题,快速恢复原图

Q&#xff1a;我手机QQ上的图片打不开了&#xff0c;怎么办呢&#xff1f;你有什么方法可以帮我解决这个问题吗&#xff1f; A&#xff1a;当然有啦&#xff0c;小编在数据恢复这个方面可是很厉害的。今天&#xff0c;小编就告诉你3个超绝的QQ图片恢复的小妙计&#xff0c;可以…

九盾叉车U型区域警示灯,高效照明和安全警示

叉车运作的环境比较复杂&#xff0c;在方便人们物流运输的同时也存在着很大的安全隐患&#xff0c;特别是叉车碰撞人的事故发生率很高&#xff0c;那我们该怎么在减少成本的同时又能避免碰撞事故的发生呢&#xff1f; 九盾叉车U型区域警示灯&#xff0c;仅需一盏灯安装在叉车尾…

有人送出几百克黄金,有人搭上百万!现在快递也不敢收了?

还记得一年多前小柴遇到过个这样的事&#xff0c;有一天早上&#xff0c;小柴还没睡醒&#xff0c;就被一京东小哥的敲门声吵醒了&#xff01; 小柴当时揉着眼睛&#xff0c;稀里糊涂的签收了这小哥送来的两个快递&#xff0c;没成想&#xff0c;不到一分钟的时间&#xff0c;…

基于多模态大语言模型的摄像头实时感知交互

简介&#xff1a; 调用本地摄像头&#xff0c;通过多模态大语言模型实时感知世界&#xff0c;并进行交互 界面&#xff1a; 代码&#xff1a; import tkinter as tk from tkinter import ttk from PIL import Image, ImageTk import cv2 import requests# 定义处理函数 def…

从源码到应用:数字药店系统与医保购药APP的开发实践

本篇文章&#xff0c;我们将深入探讨数字药店系统的开发过程&#xff0c;并介绍医保购药APP如何通过源码设计实现从基础功能到完整应用的转化。 一、数字药店系统概述 数字药店系统是一种基于互联网技术开发的在线药品销售与管理平台&#xff0c;通常包括药品展示、在线购买、…

NAT技术介绍+缺陷(内网穿透+工具),NAPT(介绍,替换过程,原理,NAT转换表)

目录 NAT技术 介绍 NAT转换表 引入 介绍 NAPT技术介绍 NAPT替换过程 NAPT原理 注意点 NAT缺陷 无法直接访问其他内网主机 内网穿透 工具 其他 NAT技术 介绍 NAT 是一种网络技术&#xff0c;它允许在一个公共 IP 地址和多个私有 IP 地址(入口路由器的wan口地址 …

屋顶上的气膜体育馆:商场创新的引流利器—轻空间

现代都市生活中&#xff0c;商场已成为不可或缺的一部分。然而&#xff0c;在竞争激烈的市场环境中&#xff0c;能够脱颖而出的商场往往依赖于独特的经营策略和创新的理念。上海嘉定某商场正是凭借其巧妙的创新思路&#xff0c;成功吸引了大量顾客&#xff0c;成为区域内的商业…

cc-proxy 常见几种代理场景

背景&#xff1a; 某项目全部内网环境&#xff0c;只有跳板机有访问互联网的权限&#xff0c;现在需要给内网的服务器更新系统&#xff0c;以及在线下载docker镜像 之前&#xff0c;使用过cc-proxy 这样的工具&#xff0c;当然现在这个工具已经停止维护了&#xff0c;使用完之…

2024源代码加密软件推荐,11款超好用的源代码加密软件推荐!

在数字化时代&#xff0c;源代码加密软件成为了保护企业与开发者心血的坚实盾牌。随着网络安全威胁的日益增多&#xff0c;选择一款高效、可靠的源代码加密工具变得至关重要。2024年&#xff0c;技术的迭代让加密软件更加成熟&#xff0c; 1.安秉源代码加密软件 安秉源代码加…

手机玩赛博朋克2077教程 GameViewer远程助你手机随时随地玩3A大作 手机怎么玩赛博朋克

手机居然也能玩赛博朋克2077&#xff0c;实现手机玩主机3A大作&#xff1f;如果你想用手机随时随地玩赛博朋克2077&#xff0c;可以用网易GameViewer远程实现。GameViewer远程作为一款专为游戏玩家打造的远程控制软件&#xff0c;让你随时随地畅玩电脑游戏&#xff0c;无论是手…

云原生 | 在 Kubernetes 中使用 Cilium 替代 Calico 网络插件实践指南!

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 简述介绍 什么是 Cilium? Cilium 是一款开源软件,它基于一种名为eBPF的新的Linux内核技术提供动力,用于透明地保护使用 Docker 和 Kubernetes 等Linux 容器管理平台中部署的应用程序服务之间的网络连接,Ciliu…

数据分析——基础

目录 一、什么是数据分析 1、什么是数据 2、数据分析 2.1 数据分析概念 2.2 数据分析要结合的维度 2.3 数据分析的目的 二、数据分析流程 三、不同需求下对应的数据呈现形式 四、数据分析的几种常见方法 一、什么是数据分析 1、什么是数据 是对客观事物的性质、状态以…

还不知道如何使用CHAT GPT?您 OUT 了!

别忘了&#xff0c;戳这个连接&#xff0c;重要的连接放三遍&#xff0c;你值得拥有&#xff01;&#xff01;&#xff01; https://ai.ashuiai.com/auth/register?inviteCodeXT16BKSO3Shttps://ai.ashuiai.com/auth/register?inviteCodeXT16BKSO3S https://ai.ashuiai.com…

别让质量问题拖垮您的企业,快看看这些隐藏的风险

质量问题的严重性 在企业运营中&#xff0c;质量问题往往是致命的隐患。一旦产品质量出现纰漏&#xff0c;可能会导致客户流失、品牌声誉受损&#xff0c;甚至带来巨大的经济损失。质量问题不仅影响短期业绩&#xff0c;更可能动摇企业的根基&#xff0c;拖垮整个业务。无论您是…

ByteTrack多目标跟踪(一)—理论基础

ByteTrack多目标跟踪 算法概述 github: https://github.com/ifzhang/ByteTrack ByteTrack是一种基于Tracking-by-Detection范式的多目标跟踪算法。 先前的多目标追踪算法一般在完成当前帧的目标检测后只会保留置信度比较大的检测框用于进行目标跟踪&#xff0c;比如图中置信度…

Git的Merge操作原理,手动merge时主分支的提交记录的保留规则

merge merge 是 Git 中用于将不同分支的历史记录合并在一起的命令。它可以将一个分支的变化合并到当前分支中,同时保留两条分支的历史记录。merge 的主要用途: 整合功能:将某个功能分支(如 feature-branch)的修改合并到主分支(如 main)中。 保留提交历史:与 git reba…

drop database xx 傻逼玩意

DB2数据库&#xff0c;就是一个逗比。下面我演示一遍&#xff0c;从创建数据库到删除数据库跑路。哈哈 1.创建数据库 db2 create database test我创建了一个数据库 test 查一下数据库目录 db2 list db directory因为我电脑只有一个盘&#xff0c;C盘&#xff0c;我是装在C盘…

npm login 或者 npm publish 超时timeout

场景&#xff1a;空闲时间想自己尝试下npm发布包&#xff0c;毕竟这东西可以不用&#xff0c;但不能不会 步骤很简单 1.npm login 2.npm publish 这里有个坑。。。因为想发布到npm上&#xff0c;所以这里的镜像源要换回https://registry.npmjs.org&#xff0c;不能使用淘宝镜像…

基于SSM+MySQL的医院在线挂号系统

系统背景 在当前数字化转型浪潮的推动下&#xff0c;医疗服务行业正经历着前所未有的变革。随着人口老龄化的加剧、患者就医需求的日益增长以及医疗资源分布不均等问题的凸显&#xff0c;传统的就医模式已难以满足患者对于便捷、高效医疗服务的需求。因此&#xff0c;构建一套基…