当前位置: 首页 > article >正文

菜鸟之路Day10一一集合进阶(三)

菜鸟之路Day10一一集合进阶(三)

作者:blue

时间:2025.1.28

文章目录

  • 菜鸟之路Day10一一集合进阶(三)
    • 0.概述
    • 1.双列集合概述
    • 2.Map
      • 2.1Map的常见API
      • 2.2Map的遍历方式
    • 3.HashMap
    • 4.LinkedHashMap
    • 5.TreeMap

0.概述

文章学习自黑马程序员BV1yW4y1Y7Ms,今天是甲辰龙年最后一天,除夕,祝大家蛇年快乐。

1.双列集合概述

特点:①双列集合一次需要存一对数据,分别为键和值

​ ②键不能重复,值可以重复

​ ③键和值是一一对应的,每一个键只能找到自己对应的值

​ ④键+值这个整体 我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”

体系结构

在这里插入图片描述

2.Map

Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用

2.1Map的常见API

package MapAPI;

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

public class MapAPIDemo {
    public static void main(String[] args) {
        //因为Map是一个接口所以只能创建它的实现类对象
        Map<String,String> mp = new HashMap<>();

        //1.V put(K key,V value) 添加元素
        //在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中
        //在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回
        mp.put("郭靖","黄蓉");
        mp.put("杨过","小龙女");
        mp.put("端木燕","灵灵");
        String res = mp.put("端木燕","欧克瑟");
        System.out.println(mp);
        System.out.println(res);//灵灵被替换了

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

        //2.V remote(Object key)  根据键删除键值对元素
        String res1 = mp.remove("杨过");
        System.out.println(mp);//杨过被删了
        System.out.println(res1);//返回值是小龙女

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

        //3.void clear() 移除所有的键值对元素

        //4.boolean containsKey(Object key) 判断集合是否包含指定的键
        System.out.println(mp.containsKey("郭靖"));//true
        System.out.println(mp.containsKey("杨过"));//false

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

        //5.boolean containsValue(Object value) 判断集合是否包含指定的值
        System.out.println(mp.containsValue("黄蓉"));//true

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

        //6.boolean isEmpty()   判断集合是否为空
        System.out.println(mp.isEmpty());//false,说明不空

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

        //7.int size()  集合长度,也就是集合中键值对的个数
        System.out.println(mp.size());//2
    }
}

2.2Map的遍历方式

方式一:键找值,将键放入单列集合中,遍历单列集合

package MapAPI;

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

public class MapDemo1 {
    public static void main(String[] args) {
        Map<String,String> mp = new HashMap<>();
        mp.put("杨过","小龙女");
        mp.put("郭靖","黄蓉");
        mp.put("张无忌","赵敏");

        //获取所有的键,把键都放到单列集合中
        Set<String> set = mp.keySet();
        for(String key:set){
            System.out.println(key+"<->"+mp.get(key));//获取对应的value
        }
    }
}

方式二:键值对(Entry对象),通过一个方法获取一个键值对对象,返回一个Set集合

package MapAPI;

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

public class MapDemo1 {
    public static void main(String[] args) {
        Map<String,String> mp = new HashMap<>();
        mp.put("杨过","小龙女");
        mp.put("郭靖","黄蓉");
        mp.put("张无忌","赵敏");

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

方式三:Lambda表达式遍历

package MapAPI;

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

public class MapDemo1 {
    public static void main(String[] args) {
        Map<String,String> mp = new HashMap<>();
        mp.put("杨过","小龙女");
        mp.put("郭靖","黄蓉");
        mp.put("张无忌","赵敏");

        //匿名内部类
        mp.forEach(new BiConsumer<String, String>() {
            @Override
            public void accept(String key, String value) {
                System.out.println(key+"->"+value);
            }
        });

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

        //Lambda表达式
        mp.forEach((String key, String value)->{
            System.out.println(key+"->"+value);
        });
    }
}

3.HashMap

特点:①无序,不重复,无所引

​ ②HashMap底层是哈希表结构的

​ ③依赖hashCode方法和equals方法保证键的唯一

​ ④如果存储的是自定义对象,需要重写hashCode和equals方法

练习一:

创建一个HashMap集合,键是学生对象,值是籍贯String

要求:同姓名,同年龄认为是同一个学生

package MapAPI;

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

public class HashMapDemo1 {
    public static void main(String[] args) {
        HashMap<Student,String> hm = new HashMap<>();
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",23);
        Student s3 = new Student("wangwu",23);

        hm.put(s1,"guangdong");
        hm.put(s2,"jiangsu");
        hm.put(s3,"shandong");

        Student s4 = new Student("zhangsan",23);
        hm.put(s4,"zhejiang");//因为我们重写了hashCode方法,所以s4被认为是重复的对象,故zhangsan的籍贯被替换成zhejiang

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

练习二:

某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A,B,C,D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

package MapAPI;

import java.util.*;

public class HashMapDemo2 {
    public static void main(String[] args) {
        String[] arr = {"A","B","C","D"};

        //随机投票
        ArrayList<String> list = new ArrayList<>();
        Random rd = new Random();
        for(int i=0;i<80;i++){
            int index = rd.nextInt(4);
            list.add(arr[index]);
        }


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

        for(String name : list){
            if(hm.containsKey(name)){//先判断存不存在
                int cnt = hm.get(name);//存在先加
                cnt++;
                hm.put(name,cnt);
            }
            else {//不存在就更新,值为1
                hm.put(name,1);
            }
        }

        System.out.println(hm);

        //获取最大值
        int max=0;
        Set<Map.Entry<String,Integer>> entries = hm.entrySet();
        for(Map.Entry<String,Integer> entry : entries){
            int cnt = entry.getValue();
            if(cnt>max) max = cnt;
        }
        System.out.println(max);


        //最大值所在的景点
        for(Map.Entry<String,Integer> entry : entries){
            int cnt = entry.getValue();
            if(cnt==max) System.out.println(entry.getKey());
        }

    }
}

4.LinkedHashMap

特点:①由键决定:有序,不重复,无索引

​ ②这里的有序是指保证存储和取出的元素顺序一致

​ 原理:底层数据结构是哈希表,只是每个键值对元素又额外多了一个双向链表的机制记录存储的顺序

除了有序,它的特点和其他双列集合的实现类都一样,在此就不过多赘述了。

5.TreeMap

①TreeMap跟TreeSet的底层原理一样,都是红黑树结构

②由键决定特性:不重复,无索引,可排序

③可排序:对键进行排序

④注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则

代码书写两种排序规则:

​ ①实现Comparable接口,指定比较规则

​ ②创建集合时传递Comparator比较器对象,指定比较规则

基本应用:

需求1:

​ 键:整数表示id;

​ 值:字符串表示商品名称;

​ 要求:按照id的升序排列,按照id的降序排列

public class TreeMapDemo1 {
    public static void main(String[] args) {
        /*TreeMap<Integer,String> tm = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-o2;//升序
                //return o2-o1 降序
            }
        });*/

        //Lambda表达式
        TreeMap<Integer,String> tm = new TreeMap<>(
           (Integer o1, Integer o2)->{
                return o1-o2;//升序
                //return o2-o1 降序
            }
        );
        tm.put(4,"aaa");
        tm.put(2,"aaa");
        tm.put(7,"ggg");
        System.out.println(tm);
    }
}

需求2:

​ 键:学生对象

​ 值:籍贯

​ 要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名视为同一个人

package MapAPI;

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;
    }

    @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);
    }

    public int getAge() {
        return age;
    }

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


    //实现Comparable接口,重写compareTo方法
    @Override
    public int compareTo(Student o) {
        //按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名视为同一个人
        int i = this.getAge()-o.getAge();
        i=i==0?this.getName().compareTo(o.getName()):i;
        return i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class TreeMapDemo2 {
    public static void main(String[] args) {
        TreeMap<Student,String> hm = new TreeMap<>();
        Student stu1 = new Student("zhangsan",17);
        Student stu2 = new Student("lisi",17);
        Student stu3 = new Student("wangwu",13);
        Student stu4 = new Student("zhangsan",17);

        hm.put(stu1,"广东");
        hm.put(stu2,"浙江");
        hm.put(stu3,"江苏");
        System.out.println(hm.put(stu4,"山东"));//由于stu4和stu1是一个人,所以广东被替换

        System.out.println(hm);
    }
}

需求3:

​ 字符串“aababcabcdabcde”

​ 请统计字符串中每一个字符出现的次数,并按照以下格式输出

​ 输出结果:a(5) b(4) c(3) d(2) e(1)

public class TreeMapDemo3 {
    public static void main(String[] args) {
        String str = "aababcabcdabcde";
        TreeMap<Character,Integer> tm = new TreeMap<>();
        for(int i=0;i<str.length();i++){
            char ch = str.charAt(i);
            if(tm.containsKey(ch)){//看看这个键在不在
                int cnt = tm.get(ch);
                cnt++;
                tm.put(ch,cnt);
            }
            else{
                tm.put(ch,1);
            }
        }
        Set<Map.Entry<Character,Integer>> entries = tm.entrySet();
        for(Map.Entry<Character,Integer> entry : entries){
            System.out.print(entry.getKey()+"("+entry.getValue()+")");
        }
    }
}

http://www.kler.cn/a/523204.html

相关文章:

  • AI编译器之——为什么大模型需要Relax?
  • FortiOS 存在身份验证绕过导致命令执行漏洞(CVE-2024-55591)
  • three.js用粒子使用canvas生成的中文字符位图材质
  • C++ unordered_map和unordered_set的使用,哈希表的实现
  • 【Elasticsearch 】悬挂索引(Dangling Indices)
  • RocketMQ原理—5.高可用+高并发+高性能架构
  • 网络工程师 (6)操作系统概述
  • 浅析 CSS 中块级框,块容器框和块框
  • 2024年记 | 凛冬将至
  • 【Java-数据结构】Java 链表面试题下 “最后一公里”:解决复杂链表问题的致胜法宝
  • 快速分析LabVIEW主要特征进行判断
  • Java面试题2025-并发编程基础(多线程、锁、阻塞队列)
  • Java基于SSM框架的互助学习平台小程序【附源码、文档】
  • GPS信号捕获【时间-频率空间搜索方法】
  • 指定dpkg安装deb包时的安装路径
  • SpringBoot 使用海康 SDK 和 flv.js 显示监控画面
  • objection的简单使用
  • 一图展示汽车和航空电子领域的安全和互操作性解决方案的概览
  • https数字签名手动验签
  • PythonFlask框架
  • Effective Objective-C 2.0 读书笔记—— objc_msgSend
  • 跨平台物联网漏洞挖掘算法评估框架设计与实现文献综述:物联网设备漏洞挖掘的挑战和机遇
  • iPhone SE(第三代) 设备详情图
  • 约瑟夫问题(信息学奥赛一本通-2037)
  • 具身智能体俯视全局的导航策略!TopV-Nav: 解锁多模态语言模型在零样本目标导航中的顶视空间推理潜力
  • 从源码深入理解One-API框架:适配器模式实现LLM接口对接