集合框架拓展--stream流的使用
Stream(JDK8新特性)
什么是Stream?
-
也叫stream流,是JDK8开始新增的一套API(java.util.stream.*),可以用于操作集合或数组中的数据
-
优势:Stream流大量地结合了Lambda的语法风格来编程,提供了一种更强大,更加简单的方式操作集合或者数组的数据,代码更简洁,可读性更好(比如:从集合中筛选数据,遍历数据)
案例:体验stream流
需求:
-
把集合中所有以''张''开头而且是三个字的元素存储到一个新的集合中
代码展示:
package com.lyc.steam;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;public class Test1 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"张三丰","张无忌","周芷若","赵敏");//把集合中所有以''张''开头而且是三个字的元素存储到一个新的集合中//原做法:ArrayList<Object> list1 = new ArrayList<>();list.forEach(s -> {if(s.startsWith("张") && s.length() == 3){list1.add(s);}});System.out.println(list1);//stream流优化:List<String> list2 = list.stream().filter(s -> s.startsWith("张") && s.length() == 3).toList();System.out.println(list2);}}
Stream流的使用步骤
-
获取数据源的stream流,相当于得到了数据源的一条流水线
-
调用流水线的各种中间方法去进行数据处理
-
获取处理的结果,调用一些常见的终结方法
stream的常用方法
获取stream流方法
-
获取集合的Stream流,
Collection提供的如下方法 | 说明 |
---|---|
default Stream <E> stream() | 获取当前对象的stream流 |
-
获得数组的Stream流
Arrays类提供的如下方法 | 说明 |
---|---|
public static <T> Stream<T> stream(T[] array) | 获取当前数组的Stream流 |
Stream类提供的如下方法 | 说明 |
---|---|
public static<T> Stream<T> of(T...values) | 获取当前接受数据的stream流 |
案例展示:
public static void main(String[] args) {//如何获取List集合的stream流?List<String> list = new ArrayList<>();Collections.addAll(list,"张三丰","张无忌","周芷若","赵敏");Stream<String> stream = list.stream();//如何获得Set集合的stream流?Set<String> set = new HashSet<>();Collections.addAll(set,"张三丰","张无忌","周芷若","赵敏");Stream<String> stream1 = set.stream();stream1.filter(s->s.contains("张")).forEach(System.out::println);//如何获得Map集合的stream流?Map<String,Double> map = new HashMap<>();map.put("张三丰",9.9);map.put("张无忌",9.8);map.put("周芷若",9.7);map.put("赵敏",9.6);//map.entrySet()返回的是一个Set集合,所以可以转换为stream流Stream<Map.Entry<String, Double>> stream2 = map.entrySet().stream();stream2.filter(s->s.getValue()>9.5 && s.getKey().contains("张")).forEach(System.out::println);//如何获取数组的数据流String[] arr = {"张三丰","张无忌","周芷若","赵敏"};//直接使用Array工具类的静态方法Stream<String> stream3 = Arrays.stream(arr);//使用Stream工具类Stream<String> arr1 = Stream.of(arr);
Stream流中间方法
-
中间方法是指调用完成后返回新的Stream流,可以继续使用(支持链式编程)
方法名 | 说明 |
---|---|
Stream<T> filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Stream<T> limit(long maxSize) | 获取前几个元素 |
Stream<T> skip(long n) | 跳过前几个元素 |
static <T> Stream<T> concat(Stream a, Stream b) | 合并a和b两个流为一个流 |
Stream<T> distinct() | 去重 |
Stream<T> sorted() | 排序 |
Stream<T> sorted(Comparator comparator) | 根据提供的Comparator进行排序 |
<R> Stream<R> map(Function mapper) | 对元素进行加工,并返回对应的新流 |
IntStream mapToInt(ToIntFunction mapper) | 返回一个IntStream其中包含将给定函数应用于此流的元素的结果 |
代码测试:
public static void main(String[] args) {List<Double> sorces = new ArrayList<>();Collections.addAll(sorces, 88.5, 99.5, 100.0, 60.5, 70.5, 80.5, 90.5, 50.5, 40.5, 30.5, 20.5);//需求1:找出成绩大于六十的学生成绩,并升序后输出 终结方法:foreachsorces.stream().filter(s->s>60).sorted().forEach(System.out::println);System.out.println("----------------------------------------------------------");ArrayList<Student> students = new ArrayList<>();students.add(new Student("张三", 18, 170.7));students.add(new Student("李四", 19, 180.7));students.add(new Student("李四", 19, 180.7));students.add(new Student("王五", 20, 190.7));students.add(new Student("赵六", 21, 200.7));students.add(new Student("钱七", 22, 210.7));students.add(new Student("孙八", 23, 220.7));//需求2:找出年龄大于等于20,小于30的学生,并按照年龄降序排序输出students.stream().filter(s->s.getAge()>=20 && s.getAge()<30).sorted((s1,s2)->s2.getAge()-s1.getAge()).forEach(System.out::println);System.out.println("-------------------------------------------------------");//需求3:找出身高最高的三名学生 limit 方法:限制数量students.stream().sorted((s1,s2)->s2.getHeight().compareTo(s1.getHeight())).limit(3).forEach(System.out::println);System.out.println("------------------------------------------------------------");//需求4:取出身高倒数的2名学生,并输出 skip方法:跳过students.stream().sorted((s1,s2)->s2.getHeight().compareTo(s1.getHeight())).skip(students.size()-2).forEach(System.out::println);System.out.println("------------------------------------------------------------");//需求5:找出身高大于等于180cm的学生的名字,要求去除重复的名字,在输出 map方法:映射,将student对象的name属性映射为字符串 distinct 方法:去重students.stream().filter(s->s.getHeight()>=180).distinct().map(Student::getName).forEach(System.out::println);System.out.println("----------------------------------------------------------------");//distinct()方法:去重,自定义类型的对象,必须重写hashCode()和equals()方法,才能去重students.stream().filter(s->s.getHeight()>=180).distinct().forEach(System.out::println);System.out.println("---------------------------------------------------------");//需求6:合并以下的两个流 concat 方法:连接两个流Stream<String> st1 = Stream.of("张三", "李四", "王五");Stream<String> st2 = Stream.of("赵六", "钱七", "孙八");Stream<String> stream = Stream.concat(st1, st2);stream.forEach(System.out::println);}}
stream流的终结方法
-
终结方法是指调用完成后,不会再返回新的stream流,没法在使用流了
stream提供的常用终结方法 | 说明 |
---|---|
void forEach(Consmer) | 对此流运算后的元素执行便历 |
long count() | 统计此流运算后的元素个数 |
Optional <T> max(Comparator<? super T> Comparator) | 获取此流运算后的最大值元素 |
Optional <T> min(Comparator<? super T> Comparator) | 获取此流运算后的最小值元素 |
-
收集Stream流:就是把Stream流操作后的结果转到集合或者数组中去返回。
-
stream流:方便操作集合/数组的手段 集合/数组:才是开发的目的
stream提供的常用终结方法 说明 R collect(Collector collector)
把流处理后的结果收集到一个指定的集合中去 Object[] toArray()
把流处理后的结果收集到一个数组中去
代码展示:
package com.lyc.steam;import com.lyc.pojo.Student;import java.util.*;import java.util.stream.Collectors;//测试stream流的终结方法public class Test4 {public static void main(String[] args) {ArrayList<Student> students = new ArrayList<>();students.add(new Student("张三", 18, 170.7));students.add(new Student("李四", 19, 180.7));students.add(new Student("李四", 19, 180.7));students.add(new Student("王五", 20, 190.7));students.add(new Student("赵六", 21, 200.7));students.add(new Student("钱七", 22, 210.7));students.add(new Student("孙八", 23, 220.7));//需求1:请计算出身高超过180的学生人数long count = students.stream().filter(s -> s.getHeight() > 180).count();System.out.println(count);System.out.println("-----------------------------------------------");//需求2:找出身高最高的学生对象,并输出Student max = students.stream().max((s1, s2) -> s1.getHeight().compareTo(s2.getHeight())).get();System.out.println(max);System.out.println("-------------------------------------------");//需求3:找出身高最矮的学生对象,并输出Student min = students.stream().min((s1, s2) -> s1.getHeight().compareTo(s2.getHeight())).get();System.out.println(min);System.out.println("----------------------------------------------");//需求4:身高超过190的学生对象,放在一个新的集合中返回// toList()方法:将流中的元素收集到一个List集合中,返回一个List集合//流,只能使用一次,所以不能再使用filter()方法,否则会报错List<Student> students1 = students.stream().filter(s->s.getHeight()>190).toList();Set<Student> collect = students.stream().filter(s -> s.getHeight() > 190).collect(Collectors.toSet());System.out.println(students1);System.out.println(collect);System.out.println("--------------------------------------------------");//需求5:找出身高大于等于190cm的学生对象,并把学生对象的名字和身高,存入到一个Map集合返回。 key:学生姓名,value:学生身高,toMap()方法:将流中的元素收集到一个Map集合中,返回一个Map集合Map<String, Double> map = students.stream().filter(s -> s.getHeight() >= 170).distinct().collect(Collectors.toMap(Student::getName, Student::getHeight));System.out.println(map);System.out.println("----------------------------------------------");//需求6:找出身高大于等于180cm的学生对象,并把学生对象的名字存入到一个数组返回。String[] array = students.stream().filter(s -> s.getHeight() >= 180).map(Student::getName).toArray(len->new String[len]);System.out.println(Arrays.toString(array));}}
注:流只能收集一次,不要想着将重复的流代码抽取封装成工具,会报错
流只是我们用来简化代码的工具,只是手段,变成集合/数组才是目的!
希望对大家有所帮助!