Stream是Java 8提供的新功能,是对集合(Collection)对象功能的增强,能对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或大批量数据操作 (bulk data operation)。 与Lambda 表达式结合,也可以提高编程效率、简洁性和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

特点

  1. Stream自己不会存储元素。
  2. Stream的操作不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  3. Stream 操作是延迟执行的。它会等到需要结果的时候才执行。也就是执行终端操作的时候。

图解

一个Stream的操作就如上图,在一个管道内,分为三个步骤,第一步是创建Stream,从集合、数组中获取一个流,第二步是中间操作链,对数据进行处理。第三步是终端操作,用来执行中间操作链,返回结果。

创建 Stream

1 将集合作为数据源,读取集合中的数据到一个流中

// 1. 实例化一个集合
List<Integer> list = new ArrayList<>();
// 2. 填充元素
Collections.addAll(list,0,1,2,3,4,5,6,7,8,9);
// 3. 读取集合中的数据,将其读取到顺序流中
// Stream<Integer> stream = list.stream();
// 3. 读取集合中的数据,将其读取到并行流中
Stream<Integer> stream = list.parallelStream();
// 4. 输出stream
System.out.println(stream);

2 将数组作为数据源,读取数组中的数据到一个流中

 // 1. 实例化一个数组
Integer[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// 2. 读取数组中的数据,将其读取到流中
Stream<Integer> stream = Arrays.stream(array);
// 3. 输出stream
System.out.println(stream);

3 使用静态方法Stream.of(),通过显式值创建一个流

Stream<Integer> stream = Stream.of(0, 1, 3, 5, 7, 9);

4 由函数创建,创建无限流

  • 迭代 public static Stream iterate(final T seed, final UnaryOperator f)

  • 生成 public static Stream generate(Supplier s)

Stream.generate(Math::random).limit(5).forEach(System.out::print); List<Integer> collect = Stream.iterate(0,i -> i + 1).limit(5).collect(Collectors.toList());

注意:使用无限流一定要配合limit截断,不然会无限制创建下去。

创建测试数据源

 /*** 学生类: 存储于集合中的数据的类型*/private static class Student implements Comparable<Student> {private String name;private int age;private int score;public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic 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 &&score == student.score &&Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age, score);}@Overridepublic int compareTo(Student o) {return score - o.score;}}
 /*** 读取数据源,将集合中存储的数据读取到数据源中* @return 流*/public static Stream<Student> getDataSource() {// 1. 实例化一个集合,存Student对象List<Student> list = new ArrayList<>();// 2. 添加若干数据Collections.addAll(list,new Student("xiaoming",17,90),new Student("xiaohong",18,100),new Student("xiaohong",21,100),new Student("xiaolan",18,90),new Student("xiaoli",19,68),new Student("xiaobai",18,72),new Student("xiaohei",20,39),new Student("xiaoke",17,93),new Student("xiaoqing",19,79),new Student("xiaofei",18,56));// 3. 读取数据源,得到Stream对象return list.stream();}

中间操作

中间操作: filter 条件过滤

可以将流中满足指定条件的数据保留,去掉不满足指定条件的数据

     // 1. 获取数据源Stream<Student> dataSource = getDataSource();// 2. 过滤掉集合中成绩不及格的学生信息dataSource.filter(s -> s.getScore() >= 60).forEach(System.out::println);

中间操作:distinct

去重,去除流中的重复的数据,这个方法是没有参数的,去重的规则与hashSet相同

  1. 比较两个对象的hashCode
  2. 再比较两个对象的equals
        // 1. 获取数据源Stream<Student> dataSource = getDataSource();// 2. 去重dataSource.distinct().forEach(System.out::println);

中间操作: sorted

sorted(): 将流中的数据,按照其对应的类实现的Comparable接口提供的比较规则进行排序

sorted(Comparator comparator): 将流中的数据按照参数接口提供的比较规则进行排序

        // 1. 获取数据源Stream<Student> dataSource = getDataSource();// 2. 对流中的数据进行排序
//        dataSource.sorted().forEach(System.out::println);// 3. 对流中的数据按照自定义的规则进行排序dataSource.sorted((s1,s2) -> s1.age - s2.age).forEach(System.out::println);

中间操作: limit & skip

limit: 限制,表示截取流中的指定数量的数据(从第 0 开始),丢弃剩余部分

skip: 跳过,表示跳过指定数量的数据,截取剩余部分

     // 2. 获取成绩的[3,5]名dataSource.sorted((s1,s2) -> s2.score - s1.score).distinct().limit(5).skip(2).forEach(System.out::println);

中间操作: map

元素映射,提供一个映射规则,将流中的每一个元素替换成指定的元素

map: 对流中的数据进行映射,用新的数据替换旧的数据

        // 1. 获取数据源Stream<Student> dataSource = getDataSource();// 2. 实际需求: 获取所有学生的名字
//      dataSource.map(Student::getName).forEach(System.out::println);
//        dataSource.map(s -> s.getName()).forEach(System.out::println);// 3. 实际需求: 获取所有学生的成绩//    这里,会得到 Stream<Integer>
//        dataSource.map(Student::getScore).forEach(System.out::println);// 4. 实际需求: 获取所有的学生成绩IntSummaryStatistics intSummaryStatistics = dataSource.mapToInt(Student::getScore).summaryStatistics();System.out.println(intSummaryStatistics.getMax());System.out.println(intSummaryStatistics.getMin());System.out.println(intSummaryStatistics.getAverage());

中间操作:flatMap

扁平化映射: 一般是用在map映射完成后,流中的数据是一个容器,而我们需要再对容器中的数据进行处理,此时使用扁平化映射,可以将流中的容器中的数据,直接读取到流中

        // 1. 实例化一个字符串数组String[] s = new String[]{ "hello","world"};// 2. 将字符串数组中的数据读取到流中Stream<String> stream = Arrays.stream(s);// 3. 需求: 统计字符串数组中所有出现的字符stream.map(e -> e.split("")).flatMap(Arrays::stream).distinct().forEach(System.out::print);
output:
helowrd

最终操作

数据准备

 public static Stream<Integer> getDataSource() {// 1. 准备一个容器List<Integer> datasource = new ArrayList<>();// 2. 向数据中添加数据Collections.addAll(datasource,0,1,2,3,4,5,6,7,8,9);// 3. 读取数据源中的数据,得到Stream对象并返回return datasource.stream();}

最终操作:collect

将流中的数据整合起来,最常见的处理是:读取流中的数据, 整合到一个容器中,得到一个集合最终操作过后,会关闭流,

     // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 流中的数据的聚合
//        List<Integer> collect = dataSource.collect(Collectors.toList());
//        Set<Integer> collect = dataSource.collect(Collectors.toSet());
//        Map<String, Integer> collect = dataSource.collect(Collectors.toMap(i -> i.toString(), i -> i));Map<Integer, String> collect = dataSource.collect(Collectors.toMap(i -> i+1, i -> i.toString()));output:
{1=0, 2=1, 3=2, 4=3, 5=4, 6=5, 7=6, 8=7, 9=8, 10=9}

最终操作 reduce

将流中的数据按照一定的规则聚合起来

        // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 最终操作
//        Integer sum = dataSource.reduce((p1, p2) -> p1 + p2).get();
//        Integer sum = dataSource.reduce(Integer::sum).get();  //使用了方法引用,效果同上// 这是一个java 8 之前复杂的匿名内部类写法,效果同上Integer sum = dataSource.reduce(new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer + integer2;}}).get();// 3. 输出结果System.out.println(sum);
output:
45

最终操作 count

统计流中的数据数量

        // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 获取流中的数据数量long count = dataSource.count();System.out.println(count);
output:
10

最终操作: forEach

遍历流中数据

        // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 遍历源中数据dataSource.forEach(System.out::println);

最终操作: max & min

max: 按照指定的对象比较规则,进行大小的比较,得出流中最大的数据

min: 按照指定的对象比较规则,进行大小的比较,得出流中最小的数据

        // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 获取流的最大值Integer integer = dataSource.max(Integer::compareTo).get();// 获取流的最小值
//        Integer integer = dataSource.min(Integer::compareTo).get();// 3. 输出结果System.out.println(integer);

最终操作: allMatch & anyMatch & noneMatch

allMatch: 只有当流中所有的元素都匹配指定的规则,才会返回true

anyMatch: 只要流中的任意数据满足指定的规则,就会返回true

noneMatch: 只有当流中所有的元素都不满足指定的规则,才会返回true

        // 1. 获取数据源Stream<Integer> dataSource = getDataSource();// 2. 匹配的操作//所有数据都大于0则返回true,否则返回false
//        boolean b = dataSource.allMatch(e -> e > 0);//存在大于8的数据则返回true,否则返回false
//        boolean b = dataSource.anyMatch(e -> e > 8);//没有一条数据大于9(即所有都小于9)则返回true,否则返回falseboolean b = dataSource.noneMatch(e -> e > 9);// 3. 输出匹配的结果System.out.println(b);

最终操作: findFirst & findAny

findFirst: 获取流中的一个元素,获取的是流中的首元素

findAny: 获取流中的一个元素,通常是首元素,但在并行流中,获取的可能不是首元素

注意:

findFirst: 在进行元素获取的时候,无论是串行流还是并行流,获取的都是首元素

findAny: 在进行元素获取的时候,串行流一定获取到的是流中的首元素,并行流获取到的可能是首元素,也可能不是

        // 1. 实例化一个集合ArrayList<Integer> datasource = new ArrayList<>();Collections.addAll(datasource,0,1,2,3,4,5);// 2. findFirst演示//parallelStream() 获取的是并行流
//        Integer integer = datasource.parallelStream().findFirst().get();
//        System.out.println(integer);// 3. findAny 演示Integer integer = datasource.parallelStream().findAny().get();

最终操作 IntStream

        // 1. 准备一个int数组,作为数据源int[] array = new int[] {0,1,2,3,4,5};// 2. 读取数据到流中,获取IntStream对象IntStream stream = Arrays.stream(array);// 3. 常见的最终操作//System.out.println(stream.max().getAsInt());         // 获取最大值
//        System.out.println(stream.min().getAsInt());         // 获取最小值// sum()不是返回OptionalInt 是因为sum() 不用做空流(即流中没数据)的处理,// 为空返回 0 就好了,而max() 与 min() 不行
//        System.out.println(stream.sum());                    // 获取数据和
//        System.out.println(stream.count());                  // 获取流中的数据的数量
//        System.out.println(stream.average().getAsDouble());  // 获取流中的数据的平均值// 4. 获取一个对流中数据的分析结果IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics();System.out.println("max = " + intSummaryStatistics.getMax());         // 获取最大值System.out.println("min = " + intSummaryStatistics.getMin());         // 获取最小值System.out.println("sum = " + intSummaryStatistics.getSum());         // 获取数据和System.out.println("average = " + intSummaryStatistics.getAverage()); // 获取平均值System.out.println("count = " + intSummaryStatistics.getCount());     // 获取数据的数量

Java中的流式编程相关推荐

  1. java中Lambda+流式编程讲解(心得篇)

    首先举一个例子来说明,我们要在一群人里面刷选一些,首先自己写一个Person类: package 任务十三__流式计算.公司;import java.util.Objects;/*** @author ...

  2. 2022-08-08 java之 Stream流式编程

    目录 一. 什么是 Stream 二.流操作 三.流与集合 什么时候计算 外部迭代和内部迭代 一次性的流 四. 一般方法 4.1. stream() / parallelStream() 4.2.fi ...

  3. Java中的流式布局(FlowLayout)

    Flowlayout默认居中对齐(FlowLayout.LEFT),组件之间的默认水平和垂直间隙为5px,组件的大小为默认的最佳大小(比如按钮的大小会保证刚好显示按钮名). 用add方法添加组件,且组 ...

  4. Java Stream流式编程

    流式编程Stream 一.简介 流式 API 从 Java8 开始引入,支持链式书写. 流只能消费一次,不能被两次消费(两次最终操作) 流在管道中流通,在节点被处理. 流[无存储],流不是一种数据结构 ...

  5. 【Java】流式编程学习笔记

    文章目录 一.流简介 二.创建流 2.1 由值创建流:of 2.2 由列表创建流:stream 2.3 由 Builder 创建流:build 2.4 由文件生成流:lines 2.5 由函数生成流 ...

  6. java 流式_Java核心教程5: 流式编程

    本次课程的标题不像之前那样易懂,是一个陌生的概念,"流式编程"是个什么东西? 在了解流式编程之前先思考一下"流",水流.电流.人流,这些都是流.而流式编程则是让 ...

  7. java流式编程(六)Collector接口

    目录 一.接口定义 二.接口泛型 一.接口定义 public interface Collector<T, A, R> {Supplier<A> supplier();BiCo ...

  8. 【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流

    Java网络编程与IO流目录: [Java网络编程与IO流]Java中IO流分为几种?字符流.字节流.缓冲流.输入流.输出流.节点流.处理流 [Java网络编程与IO流]计算机网络常见面试题高频核心考 ...

  9. java链式编程_Java 中的链式编程

    前言 ​在写项目的时候,有一个实体类有好多个属性,new 出来之后需要不停的使用setXXX( )方法,效率低而且代码可读性差,查询了下发现可以实现实体类的链式编程. public class Use ...

最新文章

  1. 查看MYSQL数据库中所有用户及拥有权限
  2. Python数据可视化1.2 数据转换
  3. Scrapy:Python的爬虫框架----原理介绍
  4. 幅度和幅值有区别吗_克拉克 (Clark) 变换中等幅值 (2/3) 和等功率 (sqrt(2/3)) 变换的公式推导...
  5. 基于事件驱动架构构建微服务第2部分:领域对象和业务规则
  6. Android 实现ListView的A-Z字母排序
  7. c++面向对象高级编程 学习四 静态、类模板、函数模板
  8. linux降低线程优先级,Linux线程优先级,行为不正常
  9. 微博:第二批共处置10106个账号 十万粉丝到一百万粉丝的账号8个
  10. webview java调用js_android WebView java与js相互调用
  11. JavaScript学习(十四)---String对象中的模式匹配方法
  12. ES6 Generator 函数
  13. 2. Windows编程基础
  14. java byte数组打印
  15. 用台达PLC485通信控制11台英威腾变频启动停止速度设定
  16. 《大秦帝国》:中国文明正源的强势生存
  17. 【论文】解读A time-dependent shared autonomous vehicle system design problem
  18. 关于GCC属性中的弱符号(weak symbol)
  19. 能带图最好的理解——克朗尼格-朋奈模型(Kronig-Penney模型)
  20. EBS杂项出库事务处理

热门文章

  1. Python 从入门到精通:一个月就够了
  2. 这个省这样规定:三类人员可直接给予青年基金项目~
  3. 20211125题目
  4. mysql 张三的语文成绩_mysql的增删改查(列子)
  5. Call to undefined method Illuminate\Database\Query\Builder::trashed()
  6. 一个 AI-backed smart manufacturing revolution 的构想:企业如何应用 AI 创新提升竞争力、降低成本、提高工作效率。
  7. 新一代自动化测试工具需要具备的功能
  8. 博士生入职华为百万年薪不算高吧?
  9. 江苏姑娘做开颅手术丈夫陪着剃光头,这爱情是真的存在。
  10. timthumb.php下载,timthumb.php