1.Map集合
1.1Map集合概述和特点【理解】
-
Map集合概述
interface Map<K,V> K:键的类型;V:值的类型
-
Map集合的特点
- 双列集合,一个键对应一个值
- 键不可以重复,值可以重复
-
Map集合的基本使用
public class MapDemo01 { public static void main(String[] args) { //创建集合对象 Map<String,String> map = new HashMap<String,String>(); //V put(K key, V value) 将指定的值与该映射中的指定键相关联 map.put("itheima001","林青霞"); map.put("itheima002","张曼玉"); map.put("itheima003","王祖贤"); map.put("itheima003","柳岩"); //输出集合对象 System.out.println(map); } }
1.2Map集合的基本功能【应用】
-
方法介绍
-
示例代码
Map<String, String> hm = new HashMap<>(); //1.添加元素 hm.put("1","一"); hm.put("2","二"); hm.put("3","三"); System.out.println(hm);//{1=一, 2=二, 3=三} //put方法的细节: //添加/覆盖 //在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null //在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。 System.out.println(hm.put("4","四"));//null System.out.println(hm.put("4","④"));//四 //2.删除元素 //如果key存在,则返回对应的value,不如不存在,则返回null System.out.println(hm.remove("5"));//null System.out.println(hm.remove("4"));//④ //3.是否包含key System.out.println(hm.containsKey("1"));//true System.out.println(hm.containsKey("4"));//false //4.是否包含value System.out.println(hm.containsValue("四"));//false System.out.println(hm.containsValue("三"));//true //5.是否为空 System.out.println(hm.isEmpty());//false //6.集合长度 System.out.println(hm.size());//3 //7.清空集合 hm.clear(); System.out.println(hm);//{}
1.3Map集合的获取功能【应用】
-
方法介绍
方法名 说明 V get(Object key) 根据键获取值 Set keySet() 获取所有键的集合 Collection values() 获取所有值的集合 Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合 -
示例代码
Map<String, String> hm = new HashMap<>(); hm.put("1","一"); hm.put("2","二"); hm.put("3","三"); System.out.println(hm.get("1"));//一 System.out.println(hm.get("4"));//null System.out.println(hm.keySet());//[1, 2, 3] System.out.println(hm.values());//[一, 二, 三] System.out.println(hm.entrySet());//[1=一, 2=二, 3=三]
1.4Map集合的遍历(方式1)【应用】
-
遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
- 把所有的丈夫给集中起来
- 遍历丈夫的集合,获取到每一个丈夫
- 根据丈夫去找对应的妻子
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
-
步骤分析
- 获取所有键的集合。用keySet()方法实现
- 遍历键的集合,获取到每一个键。用增强for实现
- 根据键去找值。用get(Object key)方法实现
-
代码实现
Map<String, String> hm = new HashMap<>(); hm.put("1","一"); hm.put("2","二"); hm.put("3","三"); //1.使用增强for遍历 Set<String> keys = hm.keySet(); for (String key : keys) { System.out.println(hm.get(key)); } //2.使用迭代器 Iterator<String> iterator = keys.iterator(); while (iterator.hasNext()){ String key = iterator.next(); System.out.println(hm.get(key)); } //3.使用lambda keys.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(hm.get(s)); } }); keys.forEach(s-> System.out.println(hm.get(s)));
1.5Map集合的遍历(方式2)【应用】
-
遍历思路
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
- 获取所有结婚证的集合
- 遍历结婚证的集合,得到每一个结婚证
- 根据结婚证获取丈夫和妻子
- 我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
-
步骤分析
- 获取所有键值对对象的集合
- Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 用增强for实现,得到每一个Map.Entry
- 根据键值对对象获取键和值
- 用getKey()得到键
- 用getValue()得到值
- 获取所有键值对对象的集合
-
代码实现
Map<String, String> hm = new HashMap<>(); hm.put("1","一"); hm.put("2","二"); hm.put("3","三"); //1.使用增强for遍历 //获取键值对对象集合 Set<Map.Entry<String, String>> entries = hm.entrySet(); //遍历得到每个键值对对象 for (Map.Entry<String, String> entry : entries) { String key = entry.getKey();//获取key String value = entry.getValue();//获取value System.out.println(key+"="+value); } //2.使用迭代器 Iterator<Map.Entry<String, String>> iterator = entries.iterator(); while (iterator.hasNext()){ Map.Entry<String,String> entry = iterator.next(); String key = entry.getKey();//获取key String value = entry.getValue();//获取value System.out.println(key+"="+value); } //3.使用lambda,层实现原理,就是获取entrySet()后,依次得到key和value hm.forEach(new BiConsumer<String, String>() { @Override public void accept(String key, String value) { System.out.println(key+"="+value); } }); hm.forEach((key,value)-> System.out.println(key+"="+value));
2.HashMap集合
2.1HashMap集合概述和特点【理解】
- HashMap底层是哈希表结构的,和HashSet一样,不同的点就是,
- 在HashMap中,如果碰到哈希值相同切equals也相同,那么覆盖原始的Entry对象
- 依赖hashCode方法和equals方法保证键的唯一
- 如果键要存储的是自定义对象,需要重写hashCode和equals方法
2.2HashMap集合应用案例【应用】
-
案例需求1
-
创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
-
要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
-
核心点:HashMap的键位置如果存储的是自定义对象,需要重写hashCode和equals方法。
HashMap<Student, String> m = new HashMap<>(); Student stu1 = new Student("zhangsan", 5); Student stu2 = new Student("lisi", 6); Student stu3 = new Student("wangwu", 7); m.put(stu1,"北京"); m.put(stu2,"上海"); m.put(stu3,"南京"); //遍历 Set<Student> keys = m.keySet(); for (Student key : keys) { System.out.println(key+"="+m.get(key)); } Set<Map.Entry<Student,String>> entries = m.entrySet(); for (Map.Entry<Student, String> entry : entries) { System.out.println(entry.getKey()+"="+entry.getValue()); } m.forEach(new BiConsumer<Student,String>(){ @Override public void accept(Student key,String value){ System.out.println(key+"="+value); } }); m.forEach((key,value)-> System.out.println(key+"="+value));
-
-
案例需求2
-
某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生只
能选择一个景点,请统计出最终哪个景点想去的人数最多。 -
思路:
- 创建一个HashMap,key代表去的景点,value代表个数
- 每统计一个,先判断景点是否存在,如果存在,则对应的value+1,如果不存在,则将景点添加到map中,并将其value设置为1
String[] position = {"A","B","C","D"}; //随机生成索引 Random random = new Random(); //投票信息 ArrayList<String> list = new ArrayList<>(); for (int i = 0; i < 80; i++) { int index = random.nextInt(position.length); list.add(position[index]); } //统计次数 HashMap<String, Integer> m = new HashMap<>(); for (String key : list) { //如果该经典已经存在,则直接++ if(m.containsKey(key)){ int value = m.get(key); value++; m.put(key,value); } else { m.put(key,1); } } System.out.println(m); //遍历出现最多次景点的是多少次 int max=0; Set<Map.Entry<String, Integer>> entries = m.entrySet(); for (Map.Entry<String, Integer> entry : entries) { int value = entry.getValue(); if(value>max) max=value; } //遍历是哪个景点出现了最多次 for (Map.Entry<String, Integer> entry : entries) { int value = entry.getValue(); if(value==max) System.out.println(entry.getKey()); }
-
3.LinkedHashMap集合
LinkedHashMap<String, String> m = new LinkedHashMap<>();
m.put("第一个","1");
m.put("第二个","2");
m.put("第三个","3");
System.out.println(m);//{第一个=1, 第二个=2, 第三个=3}
4.TreeMap集合
如果Comparable接口和Comparator比较器都实现了,则以比较器为准。
4.1TreeMap集合概述和特点【理解】
- TreeMap底层是红黑树结构
- 依赖自然排序或者比较器排序,对键进行排序
- 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
4.2TreeMap集合应用案例【应用】
-
案例需求1
-
升序排列:由于Integer中compareTo已经设置为升序比较,因此不需要重写,直接实现即可:
TreeMap<Integer, String> m = new TreeMap<>(); m.put(3,"可乐"); m.put(1,"雪碧"); m.put(2,"雷碧"); System.out.println(m);//{1=雪碧, 2=雷碧, 3=可乐}
-
降序排列:只能通过传递比较器来实现了
TreeMap<Integer, String> m = new TreeMap<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { //o1:当前要添加的元素 //o2: 表示已经在红黑树中存在的元素 return o2-o1; } }); m.put(3,"可乐"); m.put(1,"雪碧"); m.put(2,"雷碧"); System.out.println(m);//{3=可乐, 2=雷碧, 1=雪碧}
-
-
案例需求2
-
接口实现:
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; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } @Override public int compareTo(Student o) { //this: 表示当前要添加的元素 //o: 表示已经在红黑树中存在的元素 //返回值: //负数:表示当前要添加的元素是小的,存左边 //正数:表示当前要添加的元素是大的,存右边 //0: 表示当前要添加的元素已经存在,舍弃 //年龄升序排列 int result = this.getAge()-o.getAge(); //如果年龄相同,则按照姓名字母排列 result = result==0?this.getName().compareTo(o.getName()):result; return result; } }
public class Main { 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}=北京} } }
-
比较器实现:
public class Student{ private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } }
public class Main { public static void main(String[] args) { //1.创建集合 TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { int result = o1.getAge()-o2.getAge(); result=result==0?o2.getName().compareTo(o2.getName()):result; return result; } }); //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}=北京} } }
-
4.3 练习
思路分析:
-
新的统计思想:利用map集合进行统计
- 如果题目中没有要求对结果进行排序,默认使用HashMap
- 如果题目中要求对结果进行排序,请使用TreeMap
-
键:表示要统计的内容
-
值:表示次数
//1.定义字符串 String str="aababcabcdabcde"; //2.创建集合 TreeMap<Character, Integer> m = new TreeMap<>(); //3.遍历统计次数 for (int i = 0; i < str.length(); i++) { char key = str.charAt(i); if(m.containsKey(key)){ int count = m.get(key); count++; m.put(key,count); } else { m.put(key,1); } } System.out.println(m);//{a=5, b=4, c=3, d=2, e=1} //4.修改输出结果 Set<Map.Entry<Character, Integer>> entries = m.entrySet(); for (Map.Entry<Character, Integer> entry : entries) { System.out.print(entry.getKey()+"("+entry.getValue()+")"+" ");//a(5) b(4) c(3) d(2) e(1) }