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

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

作者:blue

时间:2025.1.28

文章目录

0.概述

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

1.双列集合概述

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

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

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

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

体系结构

2.Map

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

2.1Map的常见API

java 复制代码
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的遍历方式

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

java 复制代码
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集合

java 复制代码
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表达式遍历

java 复制代码
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

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

java 复制代码
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),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

java 复制代码
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的降序排列

java 复制代码
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:

​ 键:学生对象

​ 值:籍贯

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

java 复制代码
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 +
                '}';
    }
}
java 复制代码
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)

java 复制代码
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()+")");
        }
    }
}
相关推荐
董先生_ad986ad2 小时前
C# 中的 `lock` 关键字本质
开发语言·c#
Lxinccode2 小时前
Java查询数据库表信息导出Word-获取数据库实现[1]:KingbaseES
java·数据库·word·获取数据库信息·获取kingbasees信息
元亓亓亓2 小时前
Java后端开发day36--源码解析:HashMap
java·开发语言·数据结构
sd21315122 小时前
RabbitMQ 复习总结
java·rabbitmq
道剑剑非道2 小时前
QT 打包安装程序【windeployqt.exe】报错c000007d原因:Conda巨坑
开发语言·qt·conda
小邓儿◑.◑3 小时前
C++武功秘籍 | 入门知识点
开发语言·c++
_一条咸鱼_4 小时前
深度揭秘!Android HorizontalScrollView 使用原理全解析
android·面试·android jetpack
_一条咸鱼_4 小时前
揭秘 Android RippleDrawable:深入解析使用原理
android·面试·android jetpack
_一条咸鱼_4 小时前
深入剖析:Android Snackbar 使用原理的源码级探秘
android·面试·android jetpack
_一条咸鱼_4 小时前
揭秘 Android FloatingActionButton:从入门到源码深度剖析
android·面试·android jetpack