集合框架拓展--stream流的使用

发布于:2025-04-21 ⋅ 阅读:(16) ⋅ 点赞:(0)

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流的使用步骤

  1. 获取数据源的stream流,相当于得到了数据源的一条流水线

  2. 调用流水线的各种中间方法去进行数据处理

  3. 获取处理的结果,调用一些常见的终结方法

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:找出成绩大于六十的学生成绩,并升序后输出 终结方法:foreach
         sorces.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));
     }
 }
 ​

注:流只能收集一次,不要想着将重复的流代码抽取封装成工具,会报错

流只是我们用来简化代码的工具,只是手段,变成集合/数组才是目的!

希望对大家有所帮助!


网站公告

今日签到

点亮在社区的每一天
去签到