Stream流全面讲解(流的思想,获取流,中间方法,终结方法等等,包含综合对应练习题)

📅 2026/6/19 18:36:17
Stream流全面讲解(流的思想,获取流,中间方法,终结方法等等,包含综合对应练习题)
1Stream流的思想和获取Stream流Stream流的思想流水线思想java.util.stream.StreamT是函数式接口Stream本身是接口。Stream流的作用结合了Lambda表达式简化集合、数组的操作Stream流的使用步骤先得到一条Stream流流水线并把数据放上去利用Stream流中的API进行各种操作过滤转换 -中间方法。方法调用完毕之后还可以调用其他方法统计打印 -终结方法最后一步调用完毕之后不能调用其他方法所以先得到一条Stream流流水线并把数据放上去使用中间方法对流水线上的数据进行操作使用终结方法对流水线上的数据进行操作获取Stream流的方式单列集合 default StreamE stream() Collection中的默认方法双列集合 无 无法直接使用stream流数组 public staticT StreamT stream(T[] array) Arrays工具类中的静态方法一堆零散数据 public staticT StreamT of(T...values) Stream接口中的静态方法细节单列集合通过Collection中的默认方法stream()方法获取Stream流双列集合无法直接获取需通过keySet()方法或者entrySet()方法获取对应的单列Set集合然后调用单列集合中的stream方法数组可以通过Arrays工具类中的静态方法stream(T[] array)获取stream流一堆零散的数据注意这些数据的数据类型一致可以通过Stream接口中的of方法获取stream流这里Stream接口中静态方法ofT...values方法的细节//方法的形参是一个可变参数可以传递一堆零散的数据也可以传递数组//但是数组必须是引用数据类型的如果传递基本数据类型则会把整个数组当做一个元素放到Stream当中打印时会打印该数组的地址。import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Stream; public class StreamDemo1 { public static void main(String[] args) { //单列集合通过stream()方法获取Stream流 ArrayListString list new ArrayList(); Collections.addAll(list,a,b,c,d,e); StreamString stream1 list.stream(); stream1.forEach(s-System.out.println(s)); //双列集合无法直接获取 HashMapString, Integer hm new HashMap(); hm.put(aaa,111); hm.put(bbb,222); hm.put(ccc,333); hm.put(ddd,444); //第一种获取stream流的方式SetString存储键的Set集合 hm.keySet().stream().forEach(key-System.out.println(key)); //第二种获取stream流的方式 hm.entrySet().stream().forEach(entry-System.out.println(entry.getKey():entry.getValue())); // hm.entrySet().stream().forEach(new ConsumerMap.EntryString, Integer() { // Override // public void accept(Map.EntryString, Integer entry) { // System.out.println(entry.getKey():entry.getValue()); // } // }); //数组获取stream流的方式通过Arrays工具类中的静态方法stream(T[] array)方法获取 int[] arr1 {1,2,3,4,5}; Arrays.stream(arr1).forEach(i-System.out.println(i)); String[] arr2 {a,b,c,d,e}; Arrays.stream(arr2).forEach(s-System.out.println(s)); //一堆零散的数据获取stream流只不过这些零散的数据类型相同通过Stream接口中的静态方法of(T...values)获取 Stream.of(1,2,3,4).forEach(i-System.out.println(i)); Stream.of(a,b,c,d,e).forEach(s-System.out.println(s)); } }2Stream流的中间方法中间方法StreamTfilter(Predicate? super T predicate) 过滤StreamTlimit(long maxSize) 获取前几个元素StreamTskip(long n) 跳过前几个元素StreamTdistinct() 元素去重依赖hashCode和equals方法static TStreamTconcat(Stream a,Stream b) 合并a和b两个流为一个流StreamRmap(FunctionT ,R mapper) 转换流中的数据类型注意1中间方法返回新的Stream流原来的Stream流只能使用一次再次使用会出现IllegalStateException异常建议使用链式编程注意2修改Stream流中的数据不会影响原来集合或者数组中的数据1、过滤filter里面的参数 Predicate是一个函数式接口所以要实现里面的public boolean test(T a) {}方法例 public boolean test(String s){return s.startsWith(张);}//如果返回值为true表示当前数据留下//如果返回值为false表示当前数据舍弃不要2、元素去重distinct()底层是依赖HashSet所以依赖hashCode和equals方法如果泛型类型是自定义对象那么需要在自定义类中进行重写方法。3、转换流中的数据类型map参数类型为函数式接口类型Function需要实现类实现该接口然后通过new 这个实现类传递参数但是JDK8以后的匿名内部类实现了这一复杂过程的简化之后的Lambda表达式再次简化匿名内部类的书写例//Function函数式接口泛型约束的类型第一个类型流中原本的数据类型第二个类型要转成之后的类型 //apply返回值表示转换之后的数据 //当map方法执行完毕之后流上的数据就变成了整数list4.stream().map(new FunctionString, Integer() { Override public Integer apply(String s) { String[] arr s.split(-); String ageString arr[1]; int age Integer.parseInt(ageString); return age; } }).forEach(age- System.out.println(age));import java.util.ArrayList; import java.util.Collections; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; public class StreamDemo2 { public static void main(String[] args) { ArrayListString list new ArrayList(); Collections.addAll(list,刘备,孙尚香,孙权,孙策,孙仲谋,孙膑,马超); //filter过滤参数为函数式接口对象返回值为true保留返回值为false不保留 list.stream().filter(new PredicateString() { Override public boolean test(String s) { return s.startsWith(孙); } }).forEach(s-System.out.println(s)); StreamString stream1list.stream().filter(s-s.startsWith(孙)); StreamString stream2stream1.filter(s-s.length() 3); stream2.forEach(s-System.out.println(s)); System.out.println(); //StreamString stream3 stream1.filter(s-s.length()3); list.stream().filter(s-s.startsWith(孙)).filter(s-s.length() 3).forEach(s-System.out.println(s)); //limit(int n)获取流中前n个元素 list.stream().limit(3).forEach(s-System.out.println(s)); System.out.println(); //skip(int n)跳过lq中前n个元素 list.stream().skip(4).forEach(s-System.out.println(s)); System.out.println(); list.stream().limit(5).skip(2).forEach(s-System.out.println(s)); ArrayListString list1 new ArrayList(); Collections.addAll(list1,孙尚香,孙权,孙策,孙仲谋,孙膑,孙权,孙尚香); ArrayListString list2 new ArrayList(); Collections.addAll(list2,刘备,张飞,关羽); //distinct 元素去重依赖hashCode和equals方法); list1.stream().distinct().forEach(s-System.out.println(s)); System.out.println(); //Stream接口中的静态方法concat合并两个stream流 Stream.concat(list1.stream(),list2.stream()).forEach(s-System.out.println(s)); ArrayListString list4 new ArrayList(); Collections.addAll(list4,刘备-32,孙尚香-18,孙权-19,孙策-28,孙仲谋-47,孙膑-81,马超-24); //Function函数式接口泛型约束的类型第一个类型流中原本的数据类型 第二个类型要转成之后的类型 //apply返回值表示转换之后的数据 //当map方法执行完毕之后流上的数据就变成了整数 list4.stream().map(new FunctionString, Integer() { Override public Integer apply(String s) { String[] arr s.split(-); String ageString arr[1]; int age Integer.parseInt(ageString); return age; } }).forEach(age- System.out.println(age)); } }3Stream流的终结方法终结方法voidforEach(Consumer action) 遍历Longcount() 统计toArray() 收集流中的数据放到数组中collect(Collector collector) 收集流中的数据放到集合中——1、收集流中的数据放到数组中String[] arr list.stream().toArray(new IntFunctionString[]() {Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(arr));//有参//IntFunction的泛型具体类型的数组//apply的形参流中数据的个数要跟数组的长度保持一致//apply的返回值具体类型的数组//方法体就是创建数组//toArray方法的参数的作用负责创建一个指定类型的数组//toArray方法的底层会依次得到流里面的每个数据并把数据放到数组当中//toArray方法的返回值是一个装着流里面所有数据的数组toArray()方法引用toArray(Integer[] :: new);方法引用引用数组的构造方法格式数据类型[]::new范例int[]::new引用数组的构造方法就是为了创建数组。import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.function.Consumer; import java.util.function.IntFunction; public class StreamDemo3 { public static void main(String[] args) { ArrayListString list new ArrayList(); Collections.addAll(list,刘备,孙尚香,孙权,孙策,孙仲谋,孙膑,马超); list.stream().forEach(new ConsumerString() { Override public void accept(String s) { System.out.println(s); } }); //统计 long count() long countlist.stream().count(); System.out.println(count); //toArray() 收集流里面的数据把收集到的数据放到数组中 //无参 Object[] arr1 list.stream().toArray(); System.out.println(Arrays.toString(arr1)); //有参 //IntFunction的泛型具体类型的数组 //apply的形参流中数据的个数要跟数组的长度保持一致 //apply的返回值具体类型的数组 //方法体就是创建数组 //toArray方法的参数的作用负责创建一个指定类型的数组 //toArray方法的底层会依次得到流里面的每个数据并把数据放到数组当中 //toArray方法的返回值是一个装着流里面所有数据的数组 String[] arr list.stream().toArray(new IntFunctionString[]() { Override public String[] apply(int value) { return new String[value]; } }); System.out.println(Arrays.toString(arr)); String[] arr2 list.stream().toArray( value- new String[value]); System.out.println(Arrays.toString(arr2)); } }——2、收集流中的数据放到集合中collect(Collector collector) 收集流中的数据放到集合中List Set MapCollectors是java.util.stream包下的一个工具类全称java.util.stream.Collectors。它是一个工具类里面全是静态方法专门用来配合Stream.collect()做收集操作。常用的静态方法有Collectors.toList()收集为ListCollectors.toSet()收集为SetCollectors.toMap()收集为MaptoMap的两个参数为Function函数式接口对象参数一表示键的生成规则参数二表示值的生成规则具体看下面的代码及详解import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; public class StreamDemo4 { public static void main(String[] args) { ArrayListString list new ArrayList(); Collections.addAll(list, 张无忌-男-15, 周芷若-女-14, 赵敏-女-13, 张强-男-20, 张三丰-男-100, 张翠山-男-40, 张良-男-35, 王二麻子-男-37, 谢广坤-男-41 ); //收集List集合道中把所有的男性收集起来。 ListString newList1 list.stream().filter(new PredicateString(){ Override public boolean test(String s) { return 男.equals(s.split(-)[1]); } }).collect(Collectors.toList()); System.out.println(newList1); ListString newList11 list.stream() .filter( s- 男.equals(s.split(-)[1])) .collect(Collectors.toList()); //收集到Set集合当中把所有男生 SetString newList2 list.stream().filter(new PredicateString() { Override public boolean test(String s) { return 男.equals(s.split(-)[1]); } }).collect(Collectors.toSet()); System.out.println(newList2); SetString newList22 list.stream() .filter( s- 男.equals(s.split(-)[1])) .collect(Collectors.toSet()); //收集到Map集合中把所有的男生收集起来键姓名值年龄 /*toMap : 参数一表示键的生成规则 参数二表示值的生成规则 参数一 Function泛型一表示流中每一个数据的类型 泛型二表示Map集合中键的数据类型 方法apply形参依次表示流里面的每一个数据 方法体生成键的代码 返回值已经生成的键 参数二 Function泛型一表示流中的每一个数据的类型 泛型二表示Map集合中值的数据类型 方法apply形参依次表示流里面的每一个数据 方法体生成值的代码 返回值已经生成的值 */ MapString,Integer m list.stream().filter(s-男.equals(s.split(-)[1])) .collect(Collectors.toMap(new FunctionString,String() { Override public String apply(String s) { return s.split(-)[0]; } }, new FunctionString, Integer() { Override public Integer apply(String s) { return Integer.parseInt(s.split(-)[2]); } } )); System.out.println(m); MapString,Integer m1 list.stream() .filter(s-男.equals(s.split(-)[1])) .collect(Collectors.toMap( s- s.split(-)[0], s- Integer.parseInt(s.split(-)[2]))); } }4Stream流总结5Stream流练习——1、数字的过滤import java.util.ArrayList; import java.util.Collections; import java.util.function.Predicate; public class StreamDemo5{ public static void main(String[] args) { ArrayListInteger list new ArrayList(); Collections.addAll(list,1,2,3,4,5,6,7,8,9,10); list.stream().filter(new PredicateInteger() { Override public boolean test(Integer n) { return n % 2 0 ? false : true; } }).forEach(i - System.out.println(i)); list.stream() .filter(n- n % 2 0 ? false : true) .forEach(i - System.out.println(i)); } }——2、字符串过滤并收集import java.util.ArrayList; import java.util.Collections; import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; public class StreamDemo6 { public static void main(String[] args) { ArrayListString list new ArrayList(); Collections.addAll(list,孙权,23,孙尚香,19,孙膑,81,孙策,35,孙仲谋,51,马超,23,周瑜,32,瑶,18); MapString, Integer map list.stream().filter(new PredicateString() { Override public boolean test(String s) { String ageStr s.split(,)[1]; Integer age Integer.parseInt(ageStr); return age 24; } }).collect(Collectors.toMap(new FunctionString, String() { Override public String apply(String s) { return s.split(,)[0]; } },new FunctionString, Integer() { Override public Integer apply(String s) { return Integer.parseInt(s.split(,)[1]); } })); System.out.println(map); MapString, Integer m list.stream() .filter( s- {return Integer.parseInt(s.split(,)[1]) 24; }) .collect(Collectors.toMap(s- s.split(,)[0], s- Integer.parseInt(s.split(,)[1]))); } }——3、自定义对象的过滤收集import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; public class StreamDemo7 { public static void main(String[] args) { ArrayListString list1 new ArrayList(); Collections.addAll(list1,马超-23,赵子龙-29,关羽-40,张飞-38,曹操-43,牢大-35); ArrayListString list2 new ArrayList(); Collections.addAll(list2,孙尚香-19,瑶-16,孙美姬-23,王昭君-25,杨玉环-31,孙樱-20); StreamString stream1 list1.stream().filter(new PredicateString() { Override public boolean test(String s) { return s.split(-)[0].length()2; } }).limit(2); StreamString stream2 list2.stream().filter(new PredicateString() { Override public boolean test(String s) { return s.split(-)[0].startsWith(孙); } }).skip(1); ListStudent list Stream.concat(stream1,stream2).map(new FunctionString, Student() { Override public Student apply(String s) { Student stu new Student(); stu.setName(s.split(-)[0]); stu.setAge(Integer.parseInt(s.split(-)[1])); return stu; } }).collect(Collectors.toList()); System.out.println(list); } } class Student { String name; 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; } Override public String toString() { return Student [name name , age age ]; } }