【Java从入门到大牛】集合进阶下篇 我不是女神ヾ 2024-04-26 02:50 83阅读 0赞 > ? 本文由 [程序喵正在路上][Link 1] 原创,CSDN首发! > ? 系列专栏:[Java从入门到大牛][Java] > ? 首发时间:2023年8月2日 > ? 欢迎关注?点赞?收藏?留言? > ? 一以贯之的努力 不得懈怠的人生 #### 目录 #### * Collection的其他相关知识 * * 可变参数 * Collections * 综合案例 * Map集合 * * 概述 * 常用方法 * 遍历方式 * HashMap * LinkedHashMap * TreeMap * 集合的嵌套 * JDK8新特性:Stream流 * * 认识Stream * Stream的常用方法 ## Collection的其他相关知识 ## ### 可变参数 ### **什么是可变参数** 就是一种特殊形参,定义在方法、构造器的形参列表里,格式为`数据类型...参数名称;` **可变参数的特点和好处** * 特点:可以不传数据给它;可以传一个或者同时传多个数据给它;也可以传一个数组给它 * 好处:常常用来灵活地接收数据 **可变参数的注意事项** * 可变参数在方法内部就是一个数组 * 一个形参列表可变参数只能有一个 * 可变参数必须放在形参列表的最后面 **具体应用** import java.util.Arrays; /** * 目标:认识可变参数,掌握其作用 */ public class ParamTest { public static void main(String[] args) { // 特点: test(); // 不传数据 test(10); // 传输一个数据给它 test(10, 20, 30); // 传输多个数据给它 test(new int[]{ 10, 20, 30, 40}); // 传输一个数组给可变参数 } // 注意事项1:一个形参列表中,只能有一个可变参数。 // 注意事项2:可变参数必须放在形参列表的最后面 public static void test(int...nums){ // 可变参数在方法内部,本质就是一个数组。 System.out.println(nums.length); System.out.println(Arrays.toString(nums)); System.out.println("-----------------------------------------"); } } ![在这里插入图片描述][a1553c59aa244bc2b33bd75705ca9e81.png] ### Collections ### **什么是 Collections ?** 是一个用来操作集合的工具类 **Collections提供的常用静态方法** ![在这里插入图片描述][200905f1d06e4ce3aebafc5ecadbb797.png] **Collections只能支持对List集合进行排序** * 排序方式1: public static <T> void sort(List<T> list) // 对List集合中元素按照默认规则排序 注意:本方法可以直接对自定义类型的 List 集合排序,但自定义类型必须实现了 Comparable 接口,指定了比较规则才可以 * 排序方式2: public static <T> void sort(List<T> list, Comparator<? super T> c) // 对List集合中元素,按照比较器对象指定的规则进行排序 **具体应用** **学生类** public class Student implements Comparable<Student>{ private String name; private int age; private double height; @Override public int compareTo(Student o) { // 按照年龄升序排序 return this.age - o.age; } public Student() { } public Student(String name, int age, double height) { this.name = name; this.age = age; this.height = height; } 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; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}'; } } **测试类** import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * 目标:掌握Collections集合工具类的使用 */ public class CollectionsTest1 { public static void main(String[] args) { // 1、public static <T> boolean addAll(Collection<? super T> c, T...elements):为集合批量添加数据 List<String> names = new ArrayList<>(); Collections.addAll(names, "张三", "王五", "李四", "张麻子"); System.out.println(names); // 2、public static void shuffle(List<?> list):打乱List集合中的元素顺序。 Collections.shuffle(names); System.out.println(names); // 3、 public static <T> void sort(List<T> list):对List集合中的元素进行升序排序。 List<Integer> list = new ArrayList<>(); list.add(3); list.add(5); list.add(2); Collections.sort(list); System.out.println(list); List<Student> students = new ArrayList<>(); students.add(new Student("蜘蛛精",23, 169.7)); students.add(new Student("紫霞",22, 169.8)); students.add(new Student("紫霞",22, 169.8)); students.add(new Student("至尊宝",26, 165.5)); // Collections.sort(students); // System.out.println(students); // 4、public static <T> void sort(List<T> list, Comparator<? super T> c): 对List集合中元素,按照比较器对象指定的规则进行排序 Collections.sort(students, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return Double.compare(o1.getHeight(), o2.getHeight()); } }); System.out.println(students); } } ![在这里插入图片描述][52813b2799a540f19a2a3b4bea85ef03.png] ### 综合案例 ### **案例:斗地主游戏** **分析业务需求** * 总共有 54 张牌 * 点数: “3”,“4”,“5”,“6”,“7”,“8”,“9”,“10”,“J”,“Q”,“K”,“A”,“2” * 花色: “♠”, “♥”, “♣”, "♦“ * 大小王: “?” , "?“ * 斗地主:发出 51 张牌,剩下 3 张做为底牌 **分析实现** * 在启动游戏房间的时候,应该提前准备好 54 张牌 * 接着,需要完成洗牌、发牌、对牌排序、看牌 **代码示例** **Card.java** // 牌类 public class Card { private String number; // 点数 private String color; // 花色 private int size; // 每张牌的大小 public Card() { } public Card(String number, String color, int size) { this.number = number; this.color = color; this.size = size; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } @Override public String toString() { return color + number ; } } **Room.java** import java.util.ArrayList; import java.util.Collections; import java.util.List; // 房间类 public class Room { // 首先要有一副牌 private List<Card> allCards = new ArrayList<>(); public Room(){ // 1、做出54张牌,存入到集合allCards // a、点数:个数确定了,类型确定,点数从小到大排列 String[] numbers = { "3","4","5","6","7","8","9","10","J","Q","K","A","2"}; // b、花色:个数确定了,类型确定 String[] colors = { "♠", "♥", "♣", "♦"}; int size = 0; // 表示每张牌的大小 // c、遍历点数,再遍历花色,组织牌 for (String number : numbers) { // number = "3" size++; // 1 2 .... for (String color : colors) { // 得到一张牌 Card c = new Card(number, color, size); allCards.add(c); // 存入牌 } } // 单独存入大小王的 Card c1 = new Card("", "?", ++size); Card c2 = new Card("", "?", ++size); Collections.addAll(allCards, c1, c2); System.out.println("新牌:" + allCards); } /** * 启动游戏 */ public void start() { // 1、洗牌 Collections.shuffle(allCards); System.out.println("洗牌后:" + allCards); // 2、发牌,首先肯定要定义三个玩家。 List(ArrayList) Set(TreeSet) List<Card> linHuChong = new ArrayList<>(); List<Card> jiuMoZhi = new ArrayList<>(); List<Card> renYingYing = new ArrayList<>(); // 正式发牌给这三个玩家,依次发出51张牌,剩余3张做为底牌 // allCards = [♥3, ♣10, ♣4, ♥K, ♦Q, ♣2, ?, ♣8, .... for (int i = 0; i < allCards.size() - 3; i++) { Card c = allCards.get(i); // 判断牌发给谁 if(i % 3 == 0){ linHuChong.add(c); }else if(i % 3 == 1){ jiuMoZhi.add(c); }else { renYingYing.add(c); } } // 3、对3个玩家的牌进行排序 sortCards(linHuChong); sortCards(jiuMoZhi); sortCards(renYingYing); // 4、看牌 System.out.println("啊冲:" + linHuChong); System.out.println("啊鸠:" + jiuMoZhi); System.out.println("盈盈:" + renYingYing); List<Card> lastThreeCards = allCards.subList(allCards.size() - 3, allCards.size()); System.out.println("底牌:" + lastThreeCards); jiuMoZhi.addAll(lastThreeCards); sortCards(jiuMoZhi); System.out.println("啊鸠抢到地主后:" + jiuMoZhi); } /** * 集中进行排序 * @param cards */ private void sortCards(List<Card> cards) { Collections.sort(cards, (o1, o2) -> { return o2.getSize() - o1.getSize(); // 降序排序 }); } } **GameDemo.java** public class GameDemo { public static void main(String[] args) { // 1、牌类 // 2、房间 Room m = new Room(); // 3、启动游戏 m.start(); } } **执行结果** ![在这里插入图片描述][e13f4549103647f886026a6aae7b17ab.png] ## Map集合 ## ### 概述 ### **认识Map集合** * Map 集合称为双列集合,格式为`{key1=value1, key2=value2, key3=value3, ...}`,一次需要存一对数据作为一个元素 * Map 集合的每个元素 “key=value” 称为一个键值对 / 键值对对象 / 一个 Entry 对象,Map 集合也被叫做 ”键值对集合“ * Map 集合的所有键是不允许重复的,但值可以重复,键和值是一一对应的,每一个键只能找到自己对应的值 **Map集合的应用场景** 当我们需要存储一一对应的数据时,就可以考虑使用 Map 集合来做 **Map集合体系** ![在这里插入图片描述][ab62d0ca4763433189583489dca1d3a7.png] **Map集合体系的特点** 注意:Map 系列集合的特点都是由键决定的,值只是一个附属品,值是不做要求的 * HashMap(由键决定特点):无序、不重复、无索引(用得最多) * LinkedHashMap(由键决定特点):有序、不重复、无索引 * TreeMap(由键决定特点):按照大小默认升序排序、不重复、无索引 **具体应用** import java.util.LinkedHashMap; import java.util.Map; import java.util.TreeMap; /** * 目标:掌握Map集合的特点 */ public class MapTest1 { public static void main(String[] args) { // Map<String, Integer> map = new HashMap<>(); // 一行经典代码。 按照键 无序,不重复,无索引 Map<String, 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); Map<Integer, String> map1 = new TreeMap<>(); // 可排序,不重复,无索引 map1.put(23, "Java"); map1.put(23, "MySQL"); map1.put(19, "李四"); map1.put(20, "王五"); System.out.println(map1); } } ![在这里插入图片描述][165768088d4142f8be579252c7d77a64.png] ### 常用方法 ### **Map的常用方法如下:** ![在这里插入图片描述][4760190869e54c7489f6b072ca377a54.png] **具体应用** import java.util.*; /** * 目标:掌握Map集合的常用方法 */ public class MapTest2 { public static void main(String[] args) { // 1.添加元素: 无序,不重复,无索引 Map<String, 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); // 2.public int size():获取集合的大小 System.out.println("map.size: " + map.size()); // 3、public void clear():清空集合 //map.clear(); //System.out.println(map); // 4.public boolean isEmpty(): 判断集合是否为空,为空返回true ,反之! System.out.println("map.isEmpty: " + map.isEmpty()); // 5.public V get(Object key):根据键获取对应值 int v1 = map.get("手表"); System.out.println("v1: " + v1); System.out.println(map.get("手机")); // 2 System.out.println(map.get("张三")); // null // 6. public V remove(Object key):根据键删除整个元素(删除键会返回键的值) System.out.println("map.remove(\"手表\"): " + 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 Set<K> keySet(): 获取Map集合的全部键 Set<String> keys = map.keySet(); System.out.println("keys: " + keys); // 10.public Collection<V> values(); 获取Map集合的全部值 Collection<Integer> values = map.values(); System.out.println("values: " + values); // 11.把其他Map集合的数据倒入到自己集合中来(拓展) Map<String, Integer> map1 = new HashMap<>(); map1.put("java1", 10); map1.put("java2", 20); Map<String, Integer> map2 = new HashMap<>(); map2.put("java3", 10); map2.put("java2", 222); map1.putAll(map2); // putAll:把map2集合中的元素全部倒入一份到map1集合中去 System.out.println("map1: " + map1); System.out.println("map2: " + map2); } } ![在这里插入图片描述][4c9b594abf6a430793cd84c6ccbcba21.png] ### 遍历方式 ### **Map集合的遍历方式** 1. **键找值**:先获取 Map 集合全部的键,再通过遍历键来找值 2. **键值对**:把 “键值对” 看成一个整体进行遍历(难度较大) 3. **Lambda**:JDK1.8 开始之后的新技术(非常简单) **方式一:键找值** 需要用到 Map 的如下方法: ![在这里插入图片描述][b5c93bd2252341bf95c299a93e1ed027.png] 具体应用: import java.util.HashMap; import java.util.Map; import java.util.Set; /** * 目标:掌握Map集合的遍历方式1:键找值 */ public class MapTest1 { public static void main(String[] args) { // 准备一个Map集合 Map<String, 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); // 1、获取Map集合的全部键 Set<String> keys = map.keySet(); System.out.println("keys: " + keys); // 2、遍历全部的键,根据键获取其对应的值 for (String key : keys) { // 根据键获取对应的值 double value = map.get(key); System.out.println(key + "=====>" + value); } } } ![在这里插入图片描述][5fd0a40c959a4bd8a128b606097b05e7.png] **方式二:键值对** 需要用到 Map 和 Map.Entry 的如下方法: ![在这里插入图片描述][8c9a7654a020435ab0adf2e783dfc19f.png] 具体应用: import java.util.*; /** * 目标:掌握Map集合的第二种遍历方式:键值对 */ public class MapTest2 { public static void main(String[] args) { Map<String, Double> map = new HashMap<>(); map.put("蜘蛛精", 169.8); map.put("紫霞", 165.8); map.put("至尊宝", 169.5); map.put("牛魔王", 183.6); System.out.println(map); // 1、调用Map集合提供entrySet方法,把Map集合转换成键值对类型的Set集合 Set<Map.Entry<String, Double>> entries = map.entrySet(); for (Map.Entry<String, Double> entry : entries) { String key = entry.getKey(); double value = entry.getValue(); System.out.println(key + "=====>" + value); } } } ![在这里插入图片描述][07f00f0396f74b63850d87827a67628d.png] **方式三:Lambda** 需要用到 Map 的如下方法: ![在这里插入图片描述][c2ce62daa1b74820be82b29b7eb15ca6.png] 具体应用: import java.util.HashMap; import java.util.Map; /** * 目标:掌握Map集合的第三种遍历方式:Lambda */ public class MapTest3 { public static void main(String[] args) { Map<String, 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.forEach(( k, v) -> { System.out.println(k + "=====>" + v); }); } } ![在这里插入图片描述][656bd9b03bdb48a699f0c7dd66363f58.png] **案例:统计投票人数** **需求** 某个班级有 80 名学生,现在需要组织秋游活动,班长提供了四个景点依次是 A、B、C、D,每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多 **分析** 1. 将 80 个学生选择的数据拿到程序中去 2. 准备一个 Map 集合用于存储统计的结果,Map<String, Integer>,键是景点,值代表投票数量 3. 遍历 80 个学生选择的景点,每遍历一个景点,就看 Map 集合中是否存在该景点,不存在则存入 “景点=1”,存在则其对应值+1 **代码示例** import java.util.*; /** * 目标:案例:统计投票人数 */ public class MapDemo4 { public static void main(String[] args) { // 1、把80个学生选择的景点数据拿到程序中来 List<String> 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集合用于统计最终的结果 Map<String, 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); } } ![在这里插入图片描述][7e339270188a48058e99c843013a171f.png] ### HashMap ### **HashMap集合的底层原理** HashMap 跟 HashSet 的底层原理是一模一样的,都是基于哈希表实现的 实际上,原来学的 Set 系列集合的底层就是基于 Map 实现的,只是 Set 集合中的元素只要键数据,不要值数据而已 HashMap 的底层是利用键来计算哈希值的,和值无关 **HashMap集合总结** * HashMap 集合是一种增删改查数据性能都比较好的集合 * 但是它是无序的、不重复的、无索引支持的(由键决定特点) * HashMap 的键依赖 hashCode 方法和 equals 方法保证键的唯一 * 如果键存储的是自定义类型的对象,可以通过重写 hashCode 和 equals 方法,这样可以保证多个对象内容一样时,HashMap 集合就能认为是重复的 **案例:HashMap集合存储自定义对象并遍历** **需求** 创建一个 HashMap 集合,键是学生对象 Student,值是籍贯,存储几个键值对元素并遍历 **分析** 1. 定义一个学生类 2. 创建 HashMap 集合对象 3. 创建学生对象 4. 把学生添加到集合 5. 遍历集合 **代码示例** **Student.java** import java.util.Objects; public class Student implements Comparable<Student> { private String name; private int age; private double height; @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; } 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; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}'; } } **TestHashMap.java** import java.util.HashMap; import java.util.Map; public class TestHashMap { public static void main(String[] args) { Map<Student, 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), "牛头山"); map.forEach((k, v) -> System.out.println(k + ", " +v)); } } ![在这里插入图片描述][1f68ad38d54f46d18eb8dd2f80869b58.png] ### LinkedHashMap ### **LinkedHashMap集合的底层原理** 底层数据结构依然是基于哈希表实现的,只是每个键值对元素又额外地多了一个双链表的机制记录元素顺序,目的是保证元素的有序 实际上,我们原来学习的 LinkedHashSet 集合的底层原理就是 LinkedHashMap **具体应用** import java.util.LinkedHashMap; /** * 目标:掌握LinkedHashMap的底层原理 */ public class TestLinkedHashMap { public static void main(String[] args) { LinkedHashMap<String, 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); } } ![在这里插入图片描述][35a81ed5460b477babdb5b1ef3f85b0e.png] ### TreeMap ### **TreeMap** * 特点:不重复、无索引、可排序(按照键的大小默认升序排序,只能对键排序) * 原理:TreeMap 跟 TreeSet 集合的底层原理是一样的,都是基于红黑树实现的排序 **TreeMap集合同样也支持两种方式来指定排序规则** * 让类实现 Comparable 接口,重写比较规则 * TreeMap 集合有一个参数构造器,支持创建 Comparator 比较器对象,以便用来指定比较规则 **具体应用** import java.util.Comparator; import java.util.Map; import java.util.TreeMap; /** * 目标:掌握TreeMap集合的使用 */ public class TestTreeMap { public static void main(String[] args) { Map<Student, String> map = new TreeMap<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return Double.compare(o2.getHeight(), o1.getHeight()); // 降序排序 } }); // lambda表达式写法 // Map<Student, 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), "牛头山"); map.forEach((k, v) -> System.out.println(k + ", " + v)); } } ![在这里插入图片描述][cfa9bf52d790419c813cbe2bc823ca4e.png] ### 集合的嵌套 ### **什么是集合嵌套 ?** 指的是集合中的元素又是一个集合 **Map集合实现类特点** * HashMap:元素按照键是无序、不重复、无索引、值不做要求、基于哈希表 * LinkedHashMap:元素按照键是有序、不重复、无索引、值不做要求、基于哈希表 * TreeMap:元素只能按照键排序、不重复、无索引、值不做要求、可以做排序 **Map集合案例-省和市** **需求** 要求在程序中记住如下省份和其对应的城市信息,记录成功后,要求可以查询出湖北省的城市信息 * 江苏省 = 南京市,扬州市,苏州市,无锡市,常州市 湖北省 = 武汉市,孝感市,十堰市,宜昌市,鄂州市 河北省 = 石家庄市,唐山市,邢台市,保定市,张家口 **分析** * 定义一个 Map 集合,键表示省份名称,值表示城市名称,注意有多个城市 * 根据 “湖北省” 这个键获取对应的值展示即可 **代码示例** import java.util.*; /** * 目标:理解集合的嵌套 */ public class Test { public static void main(String[] args) { // 1、定义一个Map集合存储全部的省份信息,和其对应的城市信息 Map<String, List<String>> map = new HashMap<>(); List<String> cities1 = new ArrayList<>(); Collections.addAll(cities1, "南京市","扬州市","苏州市" ,"无锡市","常州市"); map.put("江苏省", cities1); List<String> cities2 = new ArrayList<>(); Collections.addAll(cities2, "武汉市","孝感市","十堰市","宜昌市","鄂州市"); map.put("湖北省", cities2); List<String> cities3 = new ArrayList<>(); Collections.addAll(cities3, "石家庄市","唐山市", "邢台市", "保定市", "张家口市"); map.put("河北省", cities3); map.forEach((k, v) -> System.out.println(k + " = " + v)); List<String> cities = map.get("湖北省"); for (String city : cities) { System.out.println(city); } } } ![在这里插入图片描述][cdfb903fab6542df936e6436faa73eb3.png] ## JDK8新特性:Stream流 ## ### 认识Stream ### **什么是 Stream ?** * 也叫做 Stream 流,是 JDK8 开始新增的一套 API(java.util.stream.\*),可以用于操作集合或者数组的数据 * 优势:Stream 流大量地结合了 Lambda 的语法风格来编程,提供了一种更加强大、更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好 **案例:体验Stream流** **需求** List<String> names = new ArrayList<>(); Collections.addAll(names, "张三丰","张无忌","周芷若","赵敏","张强"); 把集合中所有以 “张” 开头,且是 3 个字的元素存储到一个新的集合中 **代码示例** import java.util.*; import java.util.stream.Collectors; /** 目标:初步体验Stream流的方便与快捷 */ public class StreamTest1 { public static void main(String[] args) { List<String> names = new ArrayList<>(); Collections.addAll(names, "张三丰","张无忌","周芷若","赵敏","张强"); System.out.println(names); // 找出姓张,且是3个字的名字,存入到一个新集合中去 List<String> list = new ArrayList<>(); for (String name : names) { if(name.startsWith("张") && name.length() == 3){ list.add(name); } } System.out.println("一般方式: " + list); // 开始使用Stream流来解决这个需求 List<String> list2 = names.stream().filter(s -> s.startsWith("张")) .filter(a -> a.length()==3).collect(Collectors.toList()); System.out.println("Stream流: " + list2); } } ![在这里插入图片描述][b822410594bd427ebe5787230dfb648b.png] **Stream流的使用步骤** ![在这里插入图片描述][d5c169fa07644ce69bfd7a6f32de447c.png] ### Stream的常用方法 ### ![在这里插入图片描述][25294f62453841dcaffb0f8cc9bf6a19.png] **1、获取Stream流** * 获取集合的 Stream 流 ![在这里插入图片描述][c75d451d8bbd4220b61ac88301e7d8a9.png] * 获取数组的 Stream 流 ![在这里插入图片描述][a9180258a62e4b70951140542099cbd4.png] import java.util.*; import java.util.stream.Stream; /** * 目标:掌握Stream流的创建 */ public class StreamTest2 { public static void main(String[] args) { // 1、如何获取List集合的Stream流? List<String> names = new ArrayList<>(); Collections.addAll(names, "张三丰","张无忌","周芷若","赵敏","张强"); Stream<String> stream = names.stream(); // 2、如何获取Set集合的Stream流? Set<String> set = new HashSet<>(); Collections.addAll(set, "刘德华","张曼玉","蜘蛛精","马德","德玛西亚"); Stream<String> stream1 = set.stream(); stream1.filter(s -> s.contains("德")).forEach(System.out::println); // 3、如何获取Map集合的Stream流? Map<String, Double> map = new HashMap<>(); map.put("古力娜扎", 172.3); map.put("迪丽热巴", 168.3); map.put("马尔扎哈", 166.3); map.put("卡尔扎巴", 168.3); Set<String> keys = map.keySet(); Stream<String> ks = keys.stream(); Collection<Double> values = map.values(); Stream<Double> vs = values.stream(); Set<Map.Entry<String, Double>> entries = map.entrySet(); Stream<Map.Entry<String, Double>> kvs = entries.stream(); kvs.filter(e -> e.getKey().contains("巴")) .forEach(e -> System.out.println(e.getKey()+ "-->" + e.getValue())); // 4、如何获取数组的Stream流? String[] names2 = { "张翠山", "东方不败", "唐大山", "独孤求败"}; Stream<String> s1 = Arrays.stream(names2); Stream<String> s2 = Stream.of(names2); } } ![在这里插入图片描述][29b00e03f2d44835820064756c895665.png] **2、Stream流常见的中间方法** 中间方法指的是调用完成后会返回新的 Stream 流,可以继续使用(支持链式编程) ![在这里插入图片描述][89a2c3a9c3be4c799d8420ce94231adf.png] Student 类和前面的一样 import java.util.*; import java.util.stream.Stream; /** * 目标:掌握Stream流提供的常见中间方法 */ public class StreamTest3 { public static void main(String[] args) { List<Double> scores = new ArrayList<>(); Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0); // 需求1:找出成绩大于等于60分的数据,并升序后,再输出 scores.stream().filter(s -> s >= 60).sorted().forEach(System.out::println); List<Student> 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(System.out::println); // 需求3:取出身高最高的前3名学生,并输出 students.stream().sorted((o1, o2) -> Double.compare(o2.getHeight(), o1.getHeight())) .limit(3).forEach(System.out::println); 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(System.out::println); // 需求5:找出身高超过168的学生叫什么名字,要求去除重复的名字,再输出 students.stream().filter(s -> s.getHeight() > 168).map(Student::getName) .distinct().forEach(System.out::println); // distinct去重复,自定义类型的对象(希望内容一样就认为重复,重写hashCode,equals) students.stream().filter(s -> s.getHeight() > 168) .distinct().forEach(System.out::println); Stream<String> st1 = Stream.of("张三", "李四"); Stream<String> st2 = Stream.of("张三2", "李四2", "王五"); Stream<String> allSt = Stream.concat(st1, st2); allSt.forEach(System.out::println); } } **3、Stream流常见的终结方法** 终结方法指的是调用完成后,不会返回新的 Stream 了,没法继续使用流了 ![在这里插入图片描述][ab1a2902da044e51963d4008b4b703b7.png] 收集 Stream 流:就是把 Stream 流操作后的结果转回到集合或者数组中去返回 Stream 流:方便操作集合或数组的手段;集合 / 数组:才是开发中的目的 ![在这里插入图片描述][f911bd90a12646f89d1ff08f3a3ff99b.png] import java.util.*; import java.util.stream.Collectors; /** * 目标:Stream流的终结方法 */ public class StreamTest4 { public static void main(String[] args) { List<Student> 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的学生对象,并放到一个新集合中去返回 // 流只能收集一次 List<Student> students1 = students.stream().filter(a -> a.getHeight() > 170).collect(Collectors.toList()); System.out.println(students1); Set<Student> students2 = students.stream().filter(a -> a.getHeight() > 170).collect(Collectors.toSet()); System.out.println(students2); // 需求5:请找出身高超过170的学生对象,并把学生对象的名字和身高,存入到一个Map集合返回 Map<String, 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)); } } [Link 1]: https://blog.csdn.net/weixin_62511863?spm=1011.2421.3001.5343 [Java]: https://blog.csdn.net/weixin_62511863/category_12365679.html?spm=1001.2014.3001.5482 [a1553c59aa244bc2b33bd75705ca9e81.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/021a03539a5444e681dac16e1ab6e90b.png [200905f1d06e4ce3aebafc5ecadbb797.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/469370f0d6bc4fb8acb475cb6b4ddb74.png [52813b2799a540f19a2a3b4bea85ef03.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/b41ac788006b443094e57431652355a4.png [e13f4549103647f886026a6aae7b17ab.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/7ae944a096b34f4e872d38ad83e53e6f.png [ab62d0ca4763433189583489dca1d3a7.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/7c7f6d03bc324369bac306b0858ffa6b.png [165768088d4142f8be579252c7d77a64.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/70cc7ac0813442c7b7faa78701dcdbc8.png [4760190869e54c7489f6b072ca377a54.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/c10ff8d96cae4d658edb27abba71d4d5.png [4c9b594abf6a430793cd84c6ccbcba21.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/2cb7cb095b614a80981153993410e8f1.png [b5c93bd2252341bf95c299a93e1ed027.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/b9ba1006e12a4da8991ddf295c9af54b.png [5fd0a40c959a4bd8a128b606097b05e7.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/8fa71c0851d145a2bc39cb7ee81ddcda.png [8c9a7654a020435ab0adf2e783dfc19f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/c1c10cd895884695af3cb4e8e225bdaa.png [07f00f0396f74b63850d87827a67628d.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/ab6f69e260a946cfba79a67b1f090e8f.png [c2ce62daa1b74820be82b29b7eb15ca6.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/f660b7f381fa4f908f177d6399d10b26.png [656bd9b03bdb48a699f0c7dd66363f58.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/474b761545dd4149866d932f5789e928.png [7e339270188a48058e99c843013a171f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/f3544040b6364087a69568bb71f87c3d.png [1f68ad38d54f46d18eb8dd2f80869b58.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/faa02f0563564ae7b5a49cc3d81da7a7.png [35a81ed5460b477babdb5b1ef3f85b0e.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/25136c4ef52745e4a36b2024501a7427.png [cfa9bf52d790419c813cbe2bc823ca4e.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/acdc763c7dc14601ba413e0b0459b452.png [cdfb903fab6542df936e6436faa73eb3.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/95fef969974d45299af7ad1baa9bd697.png [b822410594bd427ebe5787230dfb648b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/ce6fff97f58e43eda97e46f68eda0844.png [d5c169fa07644ce69bfd7a6f32de447c.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/aa79d97b76c943b2827406744d6a29e2.png [25294f62453841dcaffb0f8cc9bf6a19.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/ff340845a8604898a107d3876d852faf.png [c75d451d8bbd4220b61ac88301e7d8a9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/0335fe578a3141468daf636dbbe22fc8.png [a9180258a62e4b70951140542099cbd4.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/073fd5dbea694352a4b587e9c91722c6.png [29b00e03f2d44835820064756c895665.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/9e80a190fdf44004b7ee7419fa17d289.png [89a2c3a9c3be4c799d8420ce94231adf.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/3037c5f7ce384dcb9f3956c122c37746.png [ab1a2902da044e51963d4008b4b703b7.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/1438a44666b243908e7c66798c02060a.png [f911bd90a12646f89d1ff08f3a3ff99b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/26/533b29132c3749b1b837aad5215d108a.png
相关 【JavaWeb从入门到实战】MySQL进阶下篇之多表查询&事务 多表查询,顾名思义就是从多张表中一次性的查询出我们想要的数据我们通过具体的案例来演示;数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令 男娘i/ 2024年04月26日 03:21/ 0 赞/ 63 阅读
相关 【Java从入门到大牛】网络编程 可以让设备中的程序与网络上的其他设备中的程序进行数据交互,也就是实现网络通信Java的 java.net.* 包下提供了网络编程的解决方案。 Myth丶恋晨/ 2024年04月26日 02:56/ 0 赞/ 93 阅读
还没有评论,来说两句吧...