菜鸟之路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()+")");
}
}
}