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

简介: 《菜鸟之路Day10——集合进阶(三)》由blue编写,发布于2025年1月28日。文章基于黑马程序员教程,介绍了Java中双列集合的特点、体系结构及Map接口的常见API和遍历方式。重点讲解了HashMap、LinkedHashMap和TreeMap的特性与应用场景,并通过多个实例演示了它们的使用方法,帮助读者深入理解集合类的高级用法。

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

作者:blue

时间:2025.1.28

0.概述

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

1.双列集合概述

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

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

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

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

体系结构

image-20250128105354148.png

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()+")");
        }
    }
}
目录
相关文章
|
3天前
|
存储 Java 程序员
菜鸟之路Day09一一集合进阶(二)
《菜鸟之路Day09——集合进阶(二)》由blue撰写于2025年1月27日。本文总结了Java集合框架的高级用法,重点介绍了泛型、Set系列集合等内容。泛型特性自JDK5引入,允许在编译阶段约束数据类型,避免运行时异常,并通过泛型类、方法和接口的应用增强了代码灵活性。Set系列集合包括HashSet、LinkedHashSet和TreeSet,分别实现了无序、有序及可排序的元素存储,支持多种遍历方式如迭代器、增强for循环和Lambda表达式。此外,文章详细解析了TreeSet的自然排序与比较器排序机制,提供了丰富的代码示例帮助理解。
38 17
|
4天前
|
存储 算法 Java
菜鸟之路Day08一一集合进阶(一)
《菜鸟之路Day08——集合进阶(一)》由blue撰写于2025年1月26日,深入探讨了五道经典算法题及单列集合的相关知识。文章首先通过自定义排序、不死神兔、猴子吃桃子、爬楼梯及其变种等题目,详细讲解了Java中数组和动态规划的应用;接着介绍了单列集合的体系结构,重点解析了Collection接口的常用方法及遍历方式(迭代器、增强for、Lambda表达式),并进一步探讨了List接口的特点与遍历方法,最后简要介绍了LinkedList的独特API。
25 6
|
6月前
|
存储 算法 调度
从菜鸟到大神的蜕变之路:Python堆与优先队列,掌握它们,你就是技术圈的MVP!
【7月更文挑战第10天】在编程进阶中,Python的heapq模块提供堆(Heap)和优先队列(Priority Queue)功能,助力高效编程。堆是特殊的完全二叉树,优先队列基于堆实现,用于按优先级处理元素。
54 0
|
存储 编译器 C++
函数璀璨之路:探索C++函数的进阶之道
函数璀璨之路:探索C++函数的进阶之道
|
存储 安全 编译器
【C++修炼之路】C++入门(下)
【C++修炼之路】C++入门(下)
121 0
【C++修炼之路】C++入门(下)
|
算法 编译器 C语言
【C++修炼之路】C++入门(上)2
【C++修炼之路】C++入门(上)
104 0
【C++修炼之路】C++入门(上)2
|
安全 C语言 C++
【C++修炼之路】C++入门(上)
【C++修炼之路】C++入门(上)
123 0
【C++修炼之路】C++入门(上)
|
安全 编译器 C#
C++菜鸟学习笔记系列(10)——数组
C++菜鸟学习笔记系列(10)——数组
92 0
|
存储 C++
C++菜鸟学习笔记系列(17)——函数基础
C++菜鸟学习笔记系列(17)——函数基础
107 0
|
NoSQL 前端开发 关系型数据库
程序员进阶之路2
程序员进阶之路2
159 0