当前位置: 首页> 汽车> 时评 > 【JAVA入门】Day31 - 双列集合 —— Map 系列

【JAVA入门】Day31 - 双列集合 —— Map 系列

时间:2025/7/12 6:51:59来源:https://blog.csdn.net/oo00Z00oo/article/details/141898706 浏览次数: 0次

【JAVA入门】Day31 - 双列集合 —— Map 系列


文章目录

  • 【JAVA入门】Day31 - 双列集合 —— Map 系列
    • 一、双列集合体系结构
    • 二、Map 的遍历方式
      • 2.1 键找值
      • 2.2 键值对遍历
      • 2.3 Lambda 表达式遍历键值对
    • 三、HashMap
      • 3.1 HashMap的创建
    • 四、LinkedHashMap
    • 五、TreeMap


        单列集合每次添加元素时,只能添加一个元素;但双列集合每次添加元素时,是添加一对元素,双列集合每次添加的一对元素,我们称为键值对(Entry)。一个键和一个值是对应的。
在这里插入图片描述
        要注意:键和值是一一对应的,每一个键只能找到自己对应的值。键不能重复,但是值是可以重复的。
        键 + 值这个整体我们称之为“键值对对象”,在 Java 中叫做“ Entry 对象”。

一、双列集合体系结构

在这里插入图片描述
        在双列集合中,Map 是顶级接口,它的所有功能可以被全部双列集合继承使用。
        Map 集合定义了很多方法,如下表。
在这里插入图片描述
        方法使用细节如下代码。

package Maps;import java.util.HashMap;
import java.util.Map;public class MapDemo1 {public static void main(String[] args) {//1.创建Map对象//Map是接口,要创建实现类对象进行多态Map<String, String> m = new HashMap<>();//2.添加键值对m.put("郭靖","黄蓉");m.put("喜羊羊","美羊羊");String value1 = m.put("开心超人","宅博士");//会覆盖上一行数据,添加时如果键不存在,直接添加该键值对,然后返回none// 如果键已存在,会覆盖原有键值对,然后将被覆盖的值返回String value2 =  m.put("开心超人","甜心超人");//返回值测试System.out.println(value1);System.out.println(value2);//打印集合System.out.println(m);          //{开心超人=宅博士, 郭靖=黄蓉, 喜羊羊=美羊羊}//3.根据键删除键值对,返回被删除的值/*String result = m.remove("郭靖");System.out.println(m);System.out.println(result);*///4.清空集合//m.clear();//System.out.println(m);//5.判断是否包含boolean keyResult = m.containsKey("郭靖");boolean valueResult = m.containsValue("美羊羊");System.out.println(keyResult);System.out.println(valueResult);//6.判断集合是否为空boolean result = m.isEmpty();System.out.println(result);//7.size集合长度int size = m.size();System.out.println(size);}
}

二、Map 的遍历方式

        Map 集合有三种遍历方式,键找值、依次获取键值对、Lambda 表达式遍历。

2.1 键找值

在这里插入图片描述        可以创建一个键的单列集合,通过每一个元素调用 get 方法来找对应的值。

package Maps;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapDemo2 {public static void main(String[] args) {//遍历方式1//1.创建Map集合对象Map<String, String> map = new HashMap<>();//2.添加元素map.put("喜羊羊","美羊羊");map.put("大大怪","小小怪");map.put("虹猫","蓝兔");//3.通过键找值//3.1 把键获取放入单列集合Set<String> keys = map.keySet();//3.2 遍历单列集合得到每一个键for (String key : keys) {//System.out.println(key);//3.3 利用键获取每一个值String value = map.get(key);System.out.println(key + " = " + value);}}
}

2.2 键值对遍历

        获取每一对键值对,然后调用 get 方法获取键和值。
在这里插入图片描述

package Maps;import java.util.HashMap;
import java.util.Map;
import java.util.Set;public class MapDemo3 {public static void main(String[] args) {//遍历方式2//1.创建Map集合对象Map<String, String> map = new HashMap<>();//2.添加元素map.put("喜羊羊","美羊羊");map.put("大大怪","小小怪");map.put("虹猫","蓝兔");//3.通过键值对对象遍历//3.1 通过一个方法获取所有键值对对象,返回一个set集合Set<Map.Entry<String, String>> entries = map.entrySet();//3.2 遍历entries集合找到所有键值对对象for (Map.Entry<String, String> entry : entries) {String key = entry.getKey();String value = entry.getValue();System.out.println(key + " = " + value);}}
}

2.3 Lambda 表达式遍历键值对

        利用Lambda表达式遍历集合。

package Maps;import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;public class MapDemo4 {public static void main(String[] args) {//遍历方式3//1.创建Map集合对象Map<String, String> map = new HashMap<>();//2.添加元素map.put("鲁迅","这句话是我说的");map.put("曹操","不可能,绝对不可能");map.put("刘备","接着奏乐,接着舞");map.put("张飞","我一枪挑了大哥!");//3.利用lambda表达式进行遍历
/*  map.forEach(new BiConsumer<String, String>() {@Overridepublic void accept(String key, String value) {System.out.println(key + "=" + value);}});*/map.forEach((key, value) -> System.out.println(key + "=" + value));}
}

三、HashMap

        HashMap 是 Map 的一个实现类。
        HashMap 中无额外方法,直接使用 Map 中的方法即可。
        HashMap 的特点由键决定:无序、不重复、无索引。
        HashMap 和 HashSet 在底层都是哈希表实现的:数组 + 链表 + 红黑树。

3.1 HashMap的创建

        在存入数据时,HashMap 是以键为准的,和值无关。它会利用键计算出哈希值,存入哈希表中。
在这里插入图片描述
        如果碰到已经存放元素的位置,还是根据键的属性值来判断。
在这里插入图片描述
        如果新元素的键和旧元素一模一样,直接覆盖之。
在这里插入图片描述
        如果新元素的键和旧的不一样,直接挂在旧元素下面,形成链表。
在这里插入图片描述
        当链表的长度超过8 & 数组长度>=64时,链表自动转成红黑树。

        根据底层结构可知,HashMap 底层存储和值没有任何关系,其依赖 hashCode() 方法和 equals() 方法保证键的唯一,如果键存储的是自定义对象,一定要重写这两个方法;但如果值存储的是自定义对象,那就不需要重写,存储和值无关。

【练习1】存储自定义对象。
需求:键为学生,值为籍贯。同年龄,同姓名认为是同一个学生。

package Maps;import java.util.HashMap;
import java.util.Set;public class HashMapDemo1 {public static void main(String[] args) {//1.创建HashMap对象HashMap<Student, String> hm = new HashMap<>();//2.三个学生对象Student s1 = new Student("zhangsan", 23);Student s2 = new Student("lisi", 24);Student s3 = new Student("wangwu", 25);Student s4 = new Student("wangwu", 25);//3.添加元素,Student是键,值是籍贯hm.put(s1, "江苏");hm.put(s2, "浙江");hm.put(s3, "胡建");hm.put(s4, "山东"); //覆盖了wangwu//4.遍历集合Set<Student> keys = hm.keySet();for (Student key : keys) {String value = hm.get(key);System.out.println(key + " = " + value);}Set<Map.Entry<Student, String>> entries = hm.entrySet();for (Map.Entry<Student, String> entry : entries) {System.out.println(entry.getKey() + " = " + entry.getValue());}hm.forEach((key, value) -> System.out.println(key + " = " + value));}
}

【练习2】利用 Map 集合统计投票人数。
需求:某个班级80名学生,现在需要组成秋游活动,班长提供了四个景点依次是((A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多。

package Maps;import java.util.*;public class HashMapDemo2 {public static void main(String[] args) {/*景点   投票次数*///存四个景点String[] arr = {"A", "B", "C", "D"};//利用随机数模拟80个同学投票,并存储投票结果ArrayList<String> list = new ArrayList<>();Random r = new Random();for(int i = 0 ; i < 80; i++) {int index = r.nextInt(arr.length);list.add(arr[index]);}HashMap<String, Integer> hm = new HashMap<>();for (String name : list) {//判断当前景点是否在集合中存在if(hm.containsKey(name)) {//获取当前景点已经被投票的次数int count = hm.get(name);//次数加一count++;//把当前景点及次数再次添加入hm中,覆盖原数据hm.put(name, count);}else{//不存在//表示当前景点是第一次出现hm.put(name, 1);}}System.out.println(hm);//3.遍历求该集合中的最大值int max = 0;Set<Map.Entry<String, Integer>> entries = hm.entrySet();for (Map.Entry<String, Integer> entry : entries) {if(entry.getValue() > max) {max = entry.getValue();}}//4.再次遍历,打印景点投票次数和最大值一样的景点for (Map.Entry<String, Integer> entry : entries) {if(entry.getValue() == max) {System.out.println(entry.getKey());}}}
}

四、LinkedHashMap

        LinkedHashMap 是 HashMap 的子类,它的特性由键决定:有序、不重复、无索引。
        这里的有序指的是保证存储和取出的元素顺序一致。它的底层和 LinkedHashSet 类似,每个键值对存入哈希表中,又额外添加了一条双链表来记录存储的顺序。
在这里插入图片描述
        在遍历时,会根据这个双链表的头结点依次遍历,和元素的存入顺序达成了一致。

package Maps;import java.util.LinkedHashMap;public class LinkedHashMapDemo {public static void main(String[] args) {//1.创建集合LinkedHashMap<String, Integer> lhm  = new LinkedHashMap<>();//2.添加元素lhm.put("123", 1);lhm.put("123", 2);lhm.put("abc", 3);lhm.put("cad", 4);//3.打印看看是不是按存储顺序System.out.println(lhm);}
}

五、TreeMap

        TreeMap 和 TreeSet 底层原理一样,都是红黑树结构的。
        TreeMap 的特性由键决定:不重复、无索引、可排序。
        TreeMap 的排序是对键的排序,默认按照键的从小到大排序(字符串就是字典顺序),也可以按照自己规定的排序规则排序,规定方式和 TreeSet 别无二致。

  • 实现 Comparable 接口,指定比较规则。
  • 创建集合时传入 Comparator 比较器对象,指定比较规则。

【练习】 需求1:键:整数表示id,值:字符串表示商品名称,要求:按照id的升序排列、按照id的降序排列。

package Maps;import java.util.Comparator;
import java.util.TreeMap;public class TreeMapDemo {public static void main(String[] args) {/*需求1:键:整数表示id,值:字符串表示商品名称,要求:按照id的升序排列、按照id的降序排列*///1.创建集合对象TreeMap<Integer,String> tm = new TreeMap<>();//2.添加元素tm.put(1,"粤利粤");tm.put(4,"雷碧");tm.put(5,"可恰可乐");tm.put(2,"康帅傅");tm.put(3,"九个核桃");//3.打印集合//默认按照键的升序进行排列System.out.println(tm);//按照id降序排列TreeMap<Integer,String> tm1 = new TreeMap<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});tm1.put(1,"粤利粤");tm1.put(4,"雷碧");tm1.put(5,"可恰可乐");tm1.put(2,"康帅傅");tm1.put(3,"九个核桃");System.out.println(tm1);}
}

【练习】 需求2:键:学生对象,值:籍贯,要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名年龄视为同一个人。

package Maps;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;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic int compareTo(Student o) {//按年龄升序int i = this.getAge() - o.getAge();//年龄一样按姓名字母顺序i = i == 0 ? this.getName().compareTo(o.getName()) : i;//姓名年龄都一样视为同一个人,TreeSet要添加的元素已经存在,就不存了return i;}
}

        Student 类实现 Comparable 接口,重写 compareTo() 方法。

package Maps;import java.util.TreeMap;public class TreeSetDemo5 {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}=江苏}}
}

【练习3】统计"aababcabcdabcde"每个字符出现次数,并按照以下格式输出:
a(5)b(4)c(3)d(2)e(1)

package Maps;import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.function.BiConsumer;public class TreeMapDemo6 {public static void main(String[] args) {//1.定义字符串String str = "aababcabcdabcde";//2.创建集合TreeMap<Character,Integer> tm = new TreeMap<>();//3.遍历字符串得到里面的每一个字符for(int i = 0; i < str.length(); i++) {char c = str.charAt(i);//如果字符没在tm中出现过,就说明其是第一次出现,就put c, 1,否则取出其count,然后++,再覆盖if(tm.containsKey(c)) {int count = tm.get(c);count++;tm.put(c, count);}else{tm.put(c, 1);}}//System.out.println(tm);//4.利用StringBuilder添加字符串按照指定格式拼接StringBuilder sb = new StringBuilder();tm.forEach((key,value) -> {sb.append(key).append("(").append(value).append(")");});System.out.println(sb);5.利用StringJoiner添加字符串按照指定格式拼接StringJoiner sj = new StringJoiner("");//sj只能add字符串,所以要把key和value后面都加一个"",把它变成字符串形式Set<Map.Entry<Character, Integer>> entries = tm.entrySet();for (Map.Entry<Character, Integer> entry : entries) {sj.add(entry.getKey() + "").add("(").add(entry.getValue() + "").add(")");}System.out.println(sj);}
}
关键字:【JAVA入门】Day31 - 双列集合 —— Map 系列

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: