Stream流粗解

2023-10-07 07:30
文章标签 stream 粗解

本文主要是介绍Stream流粗解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • Stream流粗解
    • 流简介
    • 流与集合
      • 只能遍历一次
      • 外部迭代与内部迭代
      • 流操作
      • 使用流,具体[案例点此](https://blog.csdn.net/nicew/article/details/123780811)
        • 筛选和切片
          • filter
          • distinct
          • limit
          • skip
        • 映射
          • map
          • flatMap
        • 查找和匹配
          • anyMatch
          • allMatch
          • findAny
          • findFirst
        • 规约
          • reduce

Stream流粗解

  • 声明性——更简洁,更易读
  • 可复合——更灵活
  • 可并行——性能更好

案例传送门:Stream流使用案例

  • 通过对交易的各项业务查询熟悉流的使用
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collection(groupingBy(Dish::getType));

流简介

简短定义:从支持数据处理操作的源生成的元素序列。

  • 元素序列:类似于集合,流也提供了一个接口,可以访问特定元素类型的一组有序值。与集合不同,集合的主要目的是以特定的时间和空间复杂度存储和访问元素(如ArrayList和LinkedList)。流的主要目的在于表达计算。集合讲的是数据,流讲的是计算。
  • 源: 流会使用一个提供数据的源,如集合、数组或输入/输出资源。从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素顺序与列表一致。
  • 数据处理操作:流的数据处理功能类似于数据库的操作,以及函数式编程语言的常用操作,如filter、map、reduce、find、match、sort等。流操作可以顺序执行,也可以并行执行
  • 流水线:很多流操作本身会返回一个流,所以多个操作就可以链起来,形成一个流水线。
  • 内部迭代:与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的。

示例如下,结果为:[pork, beef, chicken]

List<String> threeHighCalorDishNames = menu.stream() //源为menu,是一个列表,在Stream流案例中的Dish类可以看到定义/*** Stream<T> filter(Predicate<? super T> predicate),steam流可用的一个操作,接收一个Predicate接口对象* boolean test(T t),Predicate函数式接口定义的抽象方法,签名为 T -> booean* 经过filter操作(筛选卡路里高于300的)得到新流*/.filter(d -> d.getCalories() > 300) /*** <R> Stream<R> map(Function<? super T, ? extends R> mapper),steam流可用的一个操作,接收一个Function接口对象* R apply(T t),Function函数式接口定义的抽象方法,签名为 T -> R* 经过map操作(映射为菜名)得到新流*/.map(Dish::getName)/*** Stream<T> limit(long maxSize),steam流可用的一个操作,接收一个long型整数* 经过limit操作(只选择前三个)得到新流*/.limit(3)/*** 返回一个list*/.collect(Collectors.toList());System.out.println(threeHighCalorDishNames);

流与集合

集合:是一个内存中的数据结构,它包含数据结构中目前所有的值——集合中的每个元素都得先算出来才能添加到集合中。

  • 可比喻为DVD,视频已经完全存储到了DVD中。

流:是在概念上固定的数据结构(不能添加或删除元素),其元素时按需计算的,就像一个延迟创建的集合:在按需的一步步操作完成后才创建集合。

  • 可比喻为在线流媒体,缓存一部分看一部分,按需操作。
  • 也可比喻为用浏览器进行互联网搜索,假设搜索到多条匹配项,而可以得到一个流仅展示10个,点击下一页可展示接下来的10个,每次请求都是10个。

只能遍历一次

和迭代器类似,流只能遍历一次。遍历完成后,就称这个流已经被消费掉了。如下代码:

List<String> title = Arrays.asList("Java8", "Lambda", "Steam");
Stream<String> s = title.stream();
/*** Stream: void forEach(Consumer<? super T> action);* Consumer: void accept(T t);*/
s.forEach(System.out::println);
s.forEach(System.out::println);

结果如图:只会遍历一次,第二次遍历就抛出了异常,说明流已经被消费掉了。
在这里插入图片描述

外部迭代与内部迭代

使用Collection接口需要用户去做迭代(比如for-each),这称为外部迭代。相反,Streams库使用内部迭代——它帮你把迭代做了,还把得到的流存在了某个地方,只需要给出函数说要干什么就可以了。如下分别是集合和流的代码,说明了这种区别。

  • 集合:用for-each循环外部迭代
List<String> names = new ArrayList<>();
for (Dish d : menu) { // 显示顺序迭代菜单列表names.add(d.getName()); // 提取名称并将其添加到累加器
}
  • 集合:用背后的迭代器做外部迭代
List<String> names = new ArrayList<>();
Iterator<Dish> iterator = menu.iterator();
while (iterator.hasNext()) {Dish d = iterator.next();names.add(d.getName());
}
  • 流:内部迭代
List<String> names = menu.stream().map(Dish::getName) // 传递行为,用getName方法参数化map,提取菜名.collect(Collectors.toList());
集合:外部迭代,必须一个一个处理

你:“索菲亚,我们把玩具收起来吧。地上还有玩具吗?”
索菲亚:“有,球。”
你:“好,把球放进盒子里。还有吗?”
索菲亚:“有,娃娃。”
你:“好,把娃娃放进盒子里。还有吗?”

索菲亚:“没了,没有了。”
你:“好,我们收完了。”

流:内部迭代,可以很好的并行处理,索菲亚可以一手球一手娃娃

你:“索菲亚,把地上的玩具都收起来。”
索菲亚:“好的。”

流操作

  • 中间操作:从源获取流开始,可以进行多个类似于filter、sorted方法等中间操作,这些操作的结果还是流。
  • 终端操作:经过一系列的中间操作后,最后使用一个终端方法,从流的流水线生成结果,该结果为其他非流的值,如List、Integer等,甚至可以是void。
  • 使用流:
    • 一个数据源(如集合)来执行一个查询;
    • 一个中间操作链,形成一条流的流水线;
    • 一个终端操作,执行流水线,并能生成结果。

使用流,具体案例点此

筛选和切片
filter

Stream接口支持filter方法,该操作接受一个谓词作为参数,并返回一个包含符合谓词的元素的流。

List<Dish> vegetarianMenu = menu.stream().filter(Dish::isVegetarian).collect(toList());
distinct

Stream接口支持distinct方法,该操作会返回一个元素各异的流。

List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,4);
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);
limit

Stream接口支持limit(n)方法,该方法返回一个不超过给定长度的流。

List<Dish> dishes = menu.stream().filter(d -> d.getCalories() > 300).limit(3).collect(toList());
skip

Stream接口支持skip(n)方法,与limit方法互补,返回一个丢掉前n元素的流。

List<Dish> dishes = menu.stream().filter(d -> d.getCalories() > 300)	.skip(2).collect(toList());	
映射

Stream接口支持map和flatMap方法,接收一个函数作为参数,这个函数会作用到流的每个元素,并将其映射成一个新的元素。

map
flatMap
查找和匹配
anyMatch
allMatch
findAny
findFirst
规约
reduce

这篇关于Stream流粗解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/156951

相关文章

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

Java stream使用与执行原理

stream简介 Stream: A sequence of elements supporting sequential and parallel aggregate operations stream为sequential即单线程串行操作,parallelStream支持并行操作,本文只讨论sequential的stream。 stream常用操作 @Datastatic

Java8中的Stream,让集合操作酸爽起来

简介 java8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到集合,遍历集合可以试下lambda表达式,经常还要对集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。 Stream作为java8的新特性,基于lambda表达式,是对集合对象功能的增强,它专注于对集合对象进行各种高效、便利的聚合

Java中各种数据结构如何使用stream流

1. List 假设你有一个List<String>,你可以使用Stream来过滤、映射、排序等。 List<String> list = Arrays.asList("apple", "banana", "cherry", "date"); // 过滤操作 List<String> filteredList = list.stream() .filter(s -> s.startsW

【Node】Buffer 与 Stream

node 为什么会出现 Buffer 这个模块 在最初的时候,JavaScript 只运行在浏览器端, 对于处理 Unicode 编码的字符串很容易,但是对于处理二进制以及非 Unicode 编码的数据便无能为力。 不过对于 Server 端操作来说 网络I/O 以及 文件I/O 的处理是必须的,所以 Node 中便提供了 Buffer 类处理二进制的数据。 二进制缓冲区 Buffer

Stream插件相关的用法

文章目录 1. 概念介绍2. 使用方法2.1 StreamController2.2 StreamBuilder 3. 示例代码 我们在上一章回中介绍了管理Stream事件流相关的内容,本章回中将介绍如何使用Stream事件流输入输出数据 。闲话休提,言归正传,让我们一起Talk Flutter吧。 1. 概念介绍 我们在上一章回中看到了Stream中的事件流可以自带数据

【Python百日进阶-Web开发-音频】Day705 - 音频加载 librosa.load / librosa.stream

文章目录 一、音频加载1.1 librosa.load1.1.1 语法与参数1.1.2 例子1.1.2.1 下载并加载文件1.1.2.2 加载并重采样1.1.2.3 加载文件,从第15秒开始,加载5秒- 1.2 librosa.stream1.2.1 语法与参数1.2.2 例子1.2.2.1 一次对 256 帧的块应用短期傅里叶变换。1.2.2.2 使用较短的帧和不重叠的窗口计算流上的 m

【JAVA入门】Day34 - Stream流

【JAVA入门】Day34 - Stream流 文章目录 【JAVA入门】Day34 - Stream流一、Stream 流的作用和使用步骤1.Stream流的创建,数据的添加2. Stream流的中间方法3. Stream流的终结方法         Stream 流有什么作用?我们看一个例子: 【练习】需求:按照下面的要求完成集合的创建和遍历。 ①把所有以“张”开头

Java8 Stream流的基本使用

Java 8 中引入的 Stream API 是为了简化对集合类库(例如 List 和 Set)的操作,同时支持声明式编程风格和并行操作。Stream 不存储数据,而是对数据源进行流水线式操作,其设计核心是“将数据处理的每一步链接起来,并将操作延迟到最终需要结果时执行”。 以下是 Java 8 Stream 流的详细介绍,包括其创建、常用操作和示例代码。 1. Stream 的创建 Stre

J.U.C Review - Stream并行计算原理源码分析

文章目录 Java 8 Stream简介Stream单线程串行计算Stream多线程并行计算源码分析Stream并行计算原理Stream并行计算的性能提升 Java 8 Stream简介 自Java 8推出以来,开发者可以使用Stream接口和lambda表达式实现流式计算。这种编程风格不仅简化了对集合操作的代码,还提高了代码的可读性和性能。 Stream接口提供了多种集合