Java Map集合详解与实战

news2026/5/21 12:38:04
集合进阶Map集合一、Map集合1.1 Map概述体系各位同学前面我们已经把单列集合学习完了接下来我们要学习的是双列集合。首先我们还是先认识一下什么是双列集合。所谓双列集合就是说集合中的元素是一对一对的。格式:{key1value1 , key2value2 , key3value3 , ...}Map集合中的每一个元素是以keyvalue的形式存在的一个keyvalue就称之为一个键值对而且在Java中有一个类叫Entry类Entry的对象用来表示键值对对象Map集合也被叫做“键值对集合”。所有的Map集合有如下的特点所有键是不允许重复的值可以重复键和值是一一对应的每一个键只能找到自己对应的值。下面我们先写一个Map集合保存几个键值对体验一下Map集合的特点public class MapTest1 { public static void main(String[] args) { // MapString, Integer map new HashMap(); // 一行经典代码。按照键: 无序不重复无索引。 MapString, Integer map new LinkedHashMap(); // 特点: 有序不重复无索引。 map.put(手表, 100); map.put(手表, 220); // 后面重复的数据会覆盖前面的数据键 map.put(手机, 2); map.put(Java, 2); map.put(null, null); System.out.println(map); ​ MapInteger, String map1 new TreeMap(); // 可排序不重复无索引 map1.put(23, Java); map1.put(23, MySQL); map1.put(19, 李四); map1.put(20, 王五); System.out.println(map1); } }Map集合也有很多种在Java中使用不同的类来表示的每一种Map集合其键的特点是有些差异的值是键的一个附属值所以我们只关注键的特点就可以了。总结: 1. Map集合是什么什么时候可以考虑使用Map集合 Map集合是键值对集合 需要存储一一对应的数据时就可以考虑使用Map集合来做 ​ 2. Map集合的实现类有哪些各自的特点是 HashMap: 元素按照键是无序不重复无索引值不做要求。 LinkedHashMap: 元素按照键是有序不重复无索引值不做要求。 TreeMap元素按照建是排序不重复无索引的值不做要求。关于Map集合是什么以及Map集合的体系我们先了解到这里接下来就具体学习一下Map集合的通用方法。1.2 Map集合的常用方法各位同学上节课我们已经认识了Map集合接下来我们学习一下Map集合提供了那些方法供我们使用。由于Map是所有双列集合的父接口所以我们只需要学习Map接口中每一个方法是什么含义那么所有的Map集合方法你就都会用了。public class MapTest2 { public static void main(String[] args) { // 1.添加元素: 无序不重复无索引。 MapString, Integer map new HashMap(); map.put(手表, 100); map.put(手表, 220); map.put(手机, 2); map.put(Java, 2); map.put(null, null); System.out.println(map); // map {nullnull, 手表220, Java2, 手机2} ​ // 2.public int size():获取集合的大小 System.out.println(map.size()); ​ // 3、public void clear():清空集合 //map.clear(); //System.out.println(map); ​ // 4.public boolean isEmpty(): 判断集合是否为空为空返回true ,反之 System.out.println(map.isEmpty()); ​ // 5.public V get(Object key)根据键获取对应值 int v1 map.get(手表); System.out.println(v1); System.out.println(map.get(手机)); // 2 System.out.println(map.get(张三)); // null ​ // 6. public V remove(Object key)根据键删除整个元素(删除键会返回键的值) System.out.println(map.remove(手表)); System.out.println(map); ​ // 7.public boolean containsKey(Object key): 判断是否包含某个键 包含返回true ,反之 System.out.println(map.containsKey(手表)); // false System.out.println(map.containsKey(手机)); // true System.out.println(map.containsKey(java)); // false System.out.println(map.containsKey(Java)); // true ​ // 8.public boolean containsValue(Object value): 判断是否包含某个值。 System.out.println(map.containsValue(2)); // true System.out.println(map.containsValue(2)); // false ​ // 9.public SetK keySet(): 获取Map集合的全部键。 SetString keys map.keySet(); System.out.println(keys); ​ // 10.public CollectionV values(); 获取Map集合的全部值。 CollectionInteger values map.values(); System.out.println(values); ​ // 11.把其他Map集合的数据倒入到自己集合中来。(拓展) MapString, Integer map1 new HashMap(); map1.put(java1, 10); map1.put(java2, 20); MapString, Integer map2 new HashMap(); map2.put(java3, 10); map2.put(java2, 222); map1.putAll(map2); // putAll把map2集合中的元素全部倒入一份到map1集合中去。 System.out.println(map1); System.out.println(map2); } }1.3 Map集合遍历方式1Map集合一共有三种遍历方式:我们先来学习第一种他需要用到下面的两个方法/** * 目标掌握Map集合的遍历方式1键找值 */ public class MapTest3 { public static void main(String[] args) { // 准备一个Map集合。 MapString, Double map new HashMap(); map.put(蜘蛛精, 162.5); map.put(蜘蛛精, 169.8); map.put(紫霞, 165.8); map.put(至尊宝, 169.5); map.put(牛魔王, 183.6); System.out.println(map); // map {蜘蛛精169.8, 牛魔王183.6, 至尊宝169.5, 紫霞165.8} ​ // 1、获取Map集合的全部键 SetString keys map.keySet(); // System.out.println(keys); // [蜘蛛精, 牛魔王, 至尊宝, 紫霞] // key // 2、遍历全部的键根据键获取其对应的值 for (String key : keys) { // 根据键获取对应的值 double value map.get(key); System.out.println(key value); } } }1.4 Map集合遍历方式2各位同学接下来我们学习Map集合的第二种遍历方式这种遍历方式更加符合面向对象的思维。前面我们给大家介绍过Map集合是用来存储键值对的而每一个键值对实际上是一个Entry对象。这里Map集合的第二种方式是直接获取每一个Entry对象把Entry存储到Set集合中去再通过Entry对象获取键和值。/** * 目标掌握Map集合的第二种遍历方式键值对。 */ public class MapTest4 { public static void main(String[] args) { MapString, Double map new HashMap(); map.put(蜘蛛精, 169.8); map.put(紫霞, 165.8); map.put(至尊宝, 169.5); map.put(牛魔王, 183.6); System.out.println(map); // map {蜘蛛精169.8, 牛魔王183.6, 至尊宝169.5, 紫霞165.8} // entries [(蜘蛛精169.8), (牛魔王183.6), (至尊宝169.5), (紫霞165.8)] // entry (蜘蛛精169.8) // entry (牛魔王183.6) // ... ​ // 调用Map集合提供entrySet方法把Map集合转换成键值对类型的Set集合 SetMap.EntryString, Double entries map.entrySet(); for (Map.EntryString, Double entry : entries) { String key entry.getKey(); double value entry.getValue(); System.out.println(key ---- value); } } }1.5 Map集合遍历方式3Map集合的第三种遍历方式需要用到下面的一个方法forEach而这个方法是JDK8版本以后才有的。调用起来非常简单最好是结合的lambda表达式一起使用。/** * 目标掌握Map集合的第二种遍历方式键值对。 */ public class MapTest5 { public static void main(String[] args) { MapString, Double map new HashMap(); map.put(蜘蛛精, 169.8); map.put(紫霞, 165.8); map.put(至尊宝, 169.5); map.put(牛魔王, 183.6); System.out.println(map); // map {蜘蛛精169.8, 牛魔王183.6, 至尊宝169.5, 紫霞165.8} ​ //遍历map集合传递匿名内部类 map.forEach(new BiConsumerString, Double() { Override public void accept(String k, Double v) { System.out.println(k ---- v); } }); System.out.println(---------------------); //遍历map集合传递Lambda表达式 map.forEach((k, v) - { System.out.println(k ---- v); }); } }1.6 Map集合案例学习完Map集合的基本用法之后接下来我们做一个综合案例将Map集合运用一下。先分析需求再考虑怎么用代码实现1.首先可以将80个学生选择的景点放到一个集合中去也就是说集合中的元素是80个任意的ABCD元素 2.准备一个Map集合用来存储景点以及景点被选择的次数 3.遍历80个学生选择景点的集合得到每一个景点判断Map集合中是否包含该景点 如果不包含则存储景点1 如果包含则存获取该景点原先的值再存储景点原来的值1; 此时新值会覆盖旧值/** * 目标完成Map集合的案例统计投票人数。 */ public class MapDemo { public static void main(String[] args) { // 1、把80个学生选择的景点数据拿到程序中来。 ListString data new ArrayList(); String[] selects {A, B, C, D}; Random r new Random(); for (int i 1; i 80; i) { // 每次模拟一个学生选择一个景点存入到集合中去。 int index r.nextInt(4); // 0 1 2 3 data.add(selects[index]); } System.out.println(data); ​ // 2、开始统计每个景点的投票人数 // 准备一个Map集合用于统计最终的结果 MapString, Integer result new HashMap(); ​ // 3、开始遍历80个景点数据 for (String s : data) { // 问问Map集合中是否存在该景点 if(result.containsKey(s)){ // 说明这个景点之前统计过。其值1. 存入到Map集合中去 result.put(s, result.get(s) 1); }else { // 说明这个景点是第一次统计存入景点1 result.put(s, 1); } } System.out.println(result); } }二、Map实现类同学们我们已经学习了Map集合的常用方法以及遍历方式。下面我们要学习的是Map接口下面的是三个实现类HashMap、LinkedHashMap、TreeMap。实际上这三个实现类并没有什么特有方法需要我们学习它们的方法就是前面学习Map的方法。这里我们主要学习它们的底层原理。2.1 HashMap首先我们学习HashMap集合的底层原理。前面我们学习过HashSet的底层原理实际上HashMap底层原理和HashSet是一样的。为什么这么说呢因为我们往HashSet集合中添加元素时实际上是把元素添加到了HashMap集合中。下面是Map集合的体系结构HashMap集合的特点是由键决定的它的键是无序、不能重复而且没有索引的。再各种Map集合中也是用得最多的一种集合。刚才我们说HashSet底层就是HashMap我们可以看源码验证这一点如下图所示我们可以看到创建HashSet集合时底层帮你创建了HashMap集合往HashSet集合中添加添加元素时底层却是调用了Map集合的put方法把元素作为了键来存储。所以实际上根本没有什么HashSet集合把HashMap的集合的值忽略不看就是HashSet集合。HashSet的原理我们之前已经学过了所以HashMap是一样的底层是哈希表结构。HashMap底层数据结构: 哈希表结构 JDK8之前的哈希表 数组链表 JDK8之后的哈希表 数组链表红黑树 哈希表是一种增删改查数据性能相对都较好的数据结构 往HashMap集合中键值对数据时底层步骤如下 第1步当你第一次往HashMap集合中存储键值对时底层会创建一个长度为16的数组 第2步把键然后将键和值封装成一个对象叫做Entry对象 第3步再根据Entry对象的键计算hashCode值和值无关 第4步利用hashCode值和数组的长度做一个类似求余数的算法会得到一个索引位置 第5步判断这个索引的位置是否为null如果为null,就直接将这个Entry对象存储到这个索引位置 如果不为null则还需要进行第6步的判断 第6步继续调用equals方法判断两个对象键是否相同 如果equals返回false则以链表的形式往下挂 如果equals方法true,则认为键重复此时新的键值对会替换就的键值对。 HashMap底层需要注意这几点 1.底层数组默认长度为16如果数组中有超过12个位置已经存储了元素则会对数组进行扩容2倍 数组扩容的加载因子是0.75意思是16*0.7512 2.数组的同一个索引位置有多个元素、并且在8个元素以内(包括8)则以链表的形式存储 JDK7版本链表采用头插法新元素往链表的头部添加 JDK8版本链表采用尾插法新元素我那个链表的尾部添加 3.数组的同一个索引位置有多个元素、并且超过了8个则以红黑树形式存储从HashMap底层存储键值对的过程中我们发现决定键是否重复依赖于两个方法一个是hashCode方法、一个是equals方法。有两个键计算得到的hashCode值相同并且两个键使用equals比较为true就认为键重复。所以往Map集合中存储自定义对象作为键为了保证键的唯一性我们应该重写hashCode方法和equals方法。比如有如下案例往HashMap集合中存储Student对象作为键学生的家庭住址当做值。要求当学生对象的姓名和年龄相同时就认为键重复。public class Student implements ComparableStudent { private String name; private int age; private double height; ​ // this o Override public int compareTo(Student o) { return this.age - o.age; // 年龄升序排序 } ​ 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 Double.compare(student.height, height) 0 Objects.equals(name, student.name); } ​ Override public int hashCode() { return Objects.hash(name, age, height); } ​ public Student() { } ​ public Student(String name, int age, double height) { this.name name; this.age age; this.height height; } ​ //...get,set方法自己补全.... ​ Override public String toString() { return Student{ name name \ , age age , height height }; } }写一个测试类在测试类中创建HashMap集合键是Student类型值是Stirng类型/** * 目标掌握Map集合下的实现类HashMap集合的底层原理。 */ public class MapTest1 { public static void main(String[] args) { // 创建Map集合 MapStudent, String map new HashMap(); map.put(new Student(蜘蛛精, 25, 168.5), 盘丝洞); map.put(new Student(蜘蛛精, 25, 168.5), 水帘洞); map.put(new Student(至尊宝, 23, 163.5), 水帘洞); map.put(new Student(牛魔王, 28, 183.5), 牛头山); System.out.println(map); } }上面存储的键有两个蜘蛛精但是打印出只会有最后一个。1、HashMap的特点和底层原理 由键决定无序、不重复、无索引。HashMap底层是哈希表结构的。 HashMap集合是一种增删改查数据性能都较好的集合 但是它是无序不能重复没有索引支持的由键决定特点 HashMap的键依赖hashCode方法和equals方法保证键的唯一 如果键存储的是自定义类型的对象可以通过重写hashCode和equals方法这样可以保证多个对象内容一样时HashMap集合就能认为是重复的。 ​ 2、HashMap如何实现键的唯一性的 依赖hashCode方法和equals方法保证键的唯一。 如果键要存储的是自定义对象需要重写hashCode和equals方法。2.2 LinkedHashMap学习完HashMap集合的特点以及底层原理。接下来我们学习一下LinkedHashMap集合。LinkedHashMap集合的特点也是由键决定的有序的、不重复、无索引。/** * 目标掌握LinkedHashMap的底层原理。 */ public class MapTest2 { public static void main(String[] args) { // MapString, Integer map new HashMap(); // 按照键 无序不重复无索引。 LinkedHashMapString, Integer map new LinkedHashMap(); // 按照键 有序不重复无索引。 map.put(手表, 100); map.put(手表, 220); map.put(手机, 2); map.put(Java, 2); map.put(null, null); System.out.println(map); } }运行上面代码发现如果是LinedHashMap集合键存储和取出的顺序是一样的如果是HashMap键存储和取出的顺序是不一致的LinkedHashMap的底层原理和LinkedHashSet底层原理是一样的。底层多个一个双向链表来维护键的存储顺序。取元素时先取头节点元素然后再依次取下一个几点一直到尾结点。所以是有序的。2.3 TreeMap最后我们再学习Map集合下面的另一个子类叫TreeMap。根据我们前面学习其他Map集合的经验我们应该可以猜出TreeMap有什么特点。TreeMap集合的特点也是由键决定的默认按照键的升序排列键不重复也是无索引的。TreeMap集合和TreeSet也是一样的底层都是红黑树实现的。所以可以对键进行排序。比如往TreeMap集合中存储Student对象作为键排序方法有两种。直接看代码吧排序方式1写一个Student类让Student类实现Comparable接口//第一步先让Student类实现Comparable接口 public class Student implements ComparableStudent{ private String name; private int age; private double height; //无参数构造方法 public Student(){} //全参数构造方法 public Student(String name, int age, double height){ this.namename; this.ageage; this.heightheight; } //...get、set、toString()方法自己补上.. //按照年龄进行比较只需要在方法中让this.age和o.age相减就可以。 /* 原理 在往TreeSet集合中添加元素时add方法底层会调用compareTo方法根据该方法的 结果是正数、负数、还是零决定元素放在后面、前面还是不存。 */ Override public int compareTo(Student o) { //this表示将要添加进去的Student对象 //o: 表示集合中已有的Student对象 return this.age-o.age; } }排序方式2在创建TreeMap集合时直接传递Comparator比较器对象。/** * 目标掌握TreeMap集合的使用。 */ public class MapTest3 { public static void main(String[] args) { MapStudent, String map new TreeMap(new ComparatorStudent() { Override public int compare(Student o1, Student o2) { return Double.compare(o1.getHeight(), o2.getHeight()); } }); // MapStudent, String map new TreeMap(( o1, o2) - Double.compare(o2.getHeight(), o1.getHeight())); map.put(new Student(蜘蛛精, 25, 168.5), 盘丝洞); map.put(new Student(蜘蛛精, 25, 168.5), 水帘洞); map.put(new Student(至尊宝, 23, 163.5), 水帘洞); map.put(new Student(牛魔王, 28, 183.5), 牛头山); System.out.println(map); } }这种方式都可以对TreeMap集合中的键排序。注意只有HashMap的键才能排序HashMap值不能排序。总结: 1、TreeMap集合的特点、原理是怎么样的 根据键可排序、不重复、无索引 底层基于红黑树实现排序增删改查性能较好 ​ 2、TreeMap集合对自定义类型的对象排序有几种方式指定排序规则 2种。 ①类实现Comparable接口重写比较规则。 ②集合自定义Comparator比较器对象重写比较规则。2.4 集合嵌套各位同学到现在为止我们把Map集合和Collection集合的都已经学习完了。但是在实际开发中可能还会存在一种特殊的用法。就是把一个集合当做元素存储到另一个集合中去我们把这种用法称之为集合嵌套。下面通过一个案例给大家演示一下案例分析1.从需求中我们可以看到有三个省份每一个省份有多个城市 Map省份, List集合市 我们可以用一个Map集合的键表示省份名称而值表示省份有哪些城市 2.而又因为一个省份有多个城市同一个省份的多个城市可以再用一个List集合来存储。 所以Map集合的键是String类型而值是List集合类型 HashMapString, ListString map new HashMap();代码如下/** * 目标理解集合的嵌套。 * 江苏省 南京市,扬州市,苏州市,无锡市,常州市 * 湖北省 武汉市,孝感市,十堰市,宜昌市,鄂州市 * 河北省 石家庄市,唐山市, 邢台市, 保定市, 张家口市 */ public class MapDemo { public static void main(String[] args) { // 定义一个Map集合存储全部的省份信息和其对应的城市信息。 MapString, ListString map new HashMap(); ​ ListString cities1 new ArrayList(); Collections.addAll(cities1, 南京市,扬州市,苏州市 ,无锡市,常州市); map.put(江苏省, cities1); ​ ListString cities2 new ArrayList(); Collections.addAll(cities2, 武汉市,孝感市,十堰市,宜昌市,鄂州市); map.put(湖北省, cities2); ​ ListString cities3 new ArrayList(); Collections.addAll(cities3, 石家庄市,唐山市, 邢台市, 保定市, 张家口市); map.put(河北省, cities3); System.out.println(map); ​ ListString cities map.get(湖北省); for (String city : cities) { System.out.println(city); } ​ map.forEach((p, c) - { System.out.println(p ----- c); }); } }三、JDK8新特性Stream流各位同学接下来我们学习一个全新的知识叫做Stream流也叫Stream API。它是从JDK8以后才有的一个新特性是专业用于对集合或者数组进行便捷操作的。有多方便呢什么是Stream也叫Stream流是JDK8开始新增的一套API (java.util.stream.*)可以用于操作集合或者数组的数据。优势Stream流大量的结合了Lambda的语法风格来编程提供了一种更加强大更加简单的方式操作集合或者数组中的数据代码更简洁可读性更好。我们用一个案例体验一下然后再详细学习。3.1 Stream流体验案例需求有一个List集合元素有张三丰,张无忌,周芷若,赵敏,张强找出姓张且是3个字的名字存入到一个新集合中去。public class StreamTest { public static void main(String[] args) { // 创建集合 ListString names new ArrayList(); // 批量存储数据 Collections.addAll(names, 张三丰,张无忌,周芷若,赵敏,张强); // 打印集合 System.out.println(names); } }用传统方式来做代码是这样的// 找出姓张且是3个字的名字存入到一个新集合中去。 ListString list new ArrayList(); for (String name : names) { if(name.startsWith(张) name.length() 3){ list.add(name); } } System.out.println(list);用Stream流来做代码是这样的ps: 是不是想流水线一样一句话就写完了ListString list2 names.stream().filter(s - s.startsWith(张) s.length() 3) .collect(Collectors.toList()); System.out.println(list2); ​ System.out.println(-----------------------------); ​ ListString list3 names.stream().filter(s - s.startsWith(张)).filter(a - a.length() 3).collect(Collectors.toList()); System.out.println(list3);先不用知道这里面每一句话是什么意思具体每一句话的含义待会再一步步学习。现在只是体验一下。学习Stream流我们接下来会按照下面的步骤来学习。3.2 Stream流的创建好接下来我们正式来学习Stream流。先来学习如何创建Stream流、或者叫获取Stream流。如何获取Stream流?获取 集合 的Stream流Collection提供的如下方法说明default StreamE stream()获取当前集合对象的Stream流获取 数组 的Stream流Arrays类提供的如下 方法说明public static T StreamT stream(T[] array)获取当前数组的Stream流Stream类提供的如下 方法说明public staticT StreamTof(T... values)获取当前接收数据的Stream流直接上代码演示/** * 目标掌握Stream流的创建。 */ public class StreamTest2 { public static void main(String[] args) { // 1. 如何获取list集合的Stream流 ListString list new ArrayList(); Collections.addAll(list, 张三丰,张无忌,周芷若,赵敏,张强); StreamString stream list.stream(); ​ // 2. 如何获取set集合的Stream流 SetString set new HashSet(); Collections.addAll(set, 刘德华,张曼玉,蜘蛛精,马德,德玛西亚); StreamString stream1 set.stream(); ​ // 3. 如何获取map集合的Stream流 MapString, Double map new HashMap(); map.put(古力娜扎, 172.3); map.put(迪丽热巴, 168.3); map.put(马尔扎哈, 166.3); map.put(卡尔扎巴, 168.3); // 通过获取所有key 再获取stream流 SetString keys map.keySet(); StreamString ks keys.stream(); // 通过获取所有value 再获取stream流 CollectionDouble values map.values(); StreamDouble vs values.stream(); ​ // 通过获取entry对象 再获取stream流 SetMap.EntryString, Double entries map.entrySet(); StreamMap.EntryString, Double kvs entries.stream(); kvs.filter(s - s.getKey().contains(扎)).collect(Collectors.toList()) .forEach(s - System.out.println(s.getKey() -- s.getValue())); ​ // 4. 如何获取数组的Stream流 String[] names {张翠山, 东方不败, 唐大山, 独孤求败}; StreamString s1 Arrays.stream(names); StreamString s2 Stream.of(names); } }3.3 Stream流中间方法在上一节我们学习了创建Stream流的方法。接下来我们再来学习Stream流中间操作的方法。中间方法指的是调用完方法之后其结果是一个新的Stream流于是可以继续调用方法这样一来就可以支持链式编程或者叫流式编程。话不多说直接上代码演示/** * 目标掌握Stream流提供的常见中间方法。 */ public class StreamTest3 { public static void main(String[] args) { // 创建list集合 ListDouble scores new ArrayList(); Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0); System.out.println(scores); // 需求1找出成绩大于等于60分的数据并升序后再输出。 scores.stream().filter(s - s 60).sorted().forEach(s - System.out.println(s)); ​ System.out.println(------------------------------------------------); ​ ListStudent students new ArrayList(); Student s1 new Student(蜘蛛精, 26, 172.5); Student s2 new Student(蜘蛛精, 26, 172.5); Student s3 new Student(紫霞, 23, 167.6); Student s4 new Student(白晶晶, 25, 169.0); Student s5 new Student(牛魔王, 35, 183.3); Student s6 new Student(牛夫人, 34, 168.5); Collections.addAll(students, s1, s2, s3, s4, s5, s6); // 需求2找出年龄大于等于23,且年龄小于等于30岁的学生并按照年龄降序输出. students.stream().filter(s - s.getAge() 23 s.getAge() 30) .sorted(((o1, o2) - o2.getAge() - o1.getAge())) .forEach(s - System.out.println(s)); ​ System.out.println(------------------------------------------------); ​ // 需求3取出身高最高的前3名学生并输出。 students.stream().sorted(((o1, o2) - Double.compare(o2.getHeight(), o1.getHeight()))) .limit(3) .forEach(s - System.out.println(s)); ​ System.out.println(------------------------------------------------); ​ // 需求4取出身高倒数的2名学生并输出。 s1 s2 s3 s4 s5 s6 students.stream().sorted(((o1, o2) - Double.compare(o2.getHeight(), o1.getHeight()))) .skip(students.size() - 2) .forEach(s - System.out.println(s)); ​ System.out.println(------------------------------------------------); ​ // 需求5找出身高超过168的学生叫什么名字要求去除重复的名字再输出。 students.stream().filter(s - s.getHeight() 168) .map(Student::getName) .distinct() .forEach(System.out::println); ​ System.out.println(------------------------------------------------); ​ // distinct去重复自定义类型的对象希望内容一样就认为重复重写hashCode,equals students.stream().filter(s - s.getHeight() 168) .distinct() .forEach(System.out::println); ​ System.out.println(------------------------------------------------); ​ // 合并a和b两个流为一体 StreamString st1 Stream.of(张三, 李四); StreamString st2 Stream.of(张三2, 李四2, 王五); StreamString allSt Stream.concat(st1, st2); allSt.forEach(System.out::println); } }3.4 Stream流终结方法最后我们再学习Stream流的终结方法。这些方法的特点是调用完方法之后其结果就不再是Stream流了所以不支持链式编程。我列举了下面的几个终结方法接下来用几个案例来一个一个给同学们演示。收集Stream流就是把Stream流操作后的结果转回到集合或者数组中去返回。Stream流方便操作集合/数组的手段集合/数组才是开发中的目的。话不多说直接上代码/** * 目标Stream流的终结方法 */ public class StreamTest4 { public static void main(String[] args) { ListStudent students new ArrayList(); Student s1 new Student(蜘蛛精, 26, 172.5); Student s2 new Student(蜘蛛精, 26, 172.5); Student s3 new Student(紫霞, 23, 167.6); Student s4 new Student(白晶晶, 25, 169.0); Student s5 new Student(牛魔王, 35, 183.3); Student s6 new Student(牛夫人, 34, 168.5); Collections.addAll(students, s1, s2, s3, s4, s5, s6); // 需求1请计算出身高超过168的学生有几人。 long size students.stream().filter(s - s.getHeight() 168).count(); System.out.println(size); ​ // 需求2请找出身高最高的学生对象并输出。 Student s students.stream().max((o1, o2) - Double.compare(o1.getHeight(), o2.getHeight())).get(); System.out.println(s); ​ // 需求3请找出身高最矮的学生对象并输出。 Student ss students.stream().min((o1, o2) - Double.compare(o1.getHeight(), o2.getHeight())).get(); System.out.println(ss); ​ // 需求4请找出身高超过170的学生对象并放到一个新集合中去返回。 // 流只能收集一次。 ListStudent students1 students.stream().filter(a - a.getHeight() 170).collect(Collectors.toList()); System.out.println(students1); ​ SetStudent students2 students.stream().filter(a - a.getHeight() 170).collect(Collectors.toSet()); System.out.println(students2); ​ // 需求5请找出身高超过170的学生对象并把学生对象的名字和身高存入到一个Map集合返回。 MapString, Double map students.stream().filter(a - a.getHeight() 170) .distinct().collect(Collectors.toMap(a - a.getName(), a - a.getHeight())); System.out.println(map); ​ // Object[] arr students.stream().filter(a - a.getHeight() 170).toArray(); Student[] arr students.stream().filter(a - a.getHeight() 170).toArray(len - new Student[len]); System.out.println(Arrays.toString(arr)); } }到这里关于Stream流的操常见操作我们就已经学习完了。当然Stream流还有一些其他的方法同学们遇到了也可以自己再研究一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2631511.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…