1 前言

Stream 是 Java 8 中为方便操作集合及其元素而定制的接口,它将要处理的元素集合看作一种流,对流中的元素进行过滤、排序、映射、聚合等操作。使用 Stream API,就好像使用 SQL 中的 select 语句操作数据库,非常快捷高效,一行代码可以实现很多功能。

(1)Stream 操作分类

  • 中间操作:每次操作返回一个新的 Stream 对象(主要操作有:filter、map、sorted、peek、distinct、limit、skip 等)。
  • 终端操作:每次操作返回一个值或集合,每个流只能进行一次终端操作(主要操作有:forEach、max、min、count、reduce、collect、anyMatch、allMatch、findFirst、findAny 等)。

(2)Stream 特性

  • 不存储数据:Stream 不是数据结构,不存储数据,只提供了一系列操作数据的接口。
  • 不改变数据源:终端操作后会产生一个新的值或集合。
  • 延迟执行:只有调用终端操作时,中间操作才会执行。

在学习 Stream 之前,需要先掌握 Lambda 表达式和 Optional,详见→Lambda 表达式总结Optional 详解

2 Stream 的创建

(1)Collection

//Collection 类接口
default Stream<E> stream() //顺序流
default Stream<E> parallelStream() //并行流 //案例
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流

说明:List 和 Set 是 Collection 的子类。

(2)Arrays

//Arrays 类接口
public static <T> Stream<T> stream(T[] array) //案例
Integer[] nums = new Integer[10]{8, 2, 5, 6};
Stream<Integer> stream = Arrays.stream(nums);

(3)Stream

//Stream 类接口
public static<T> Stream<T> of(T... values) //Arrays.stream(values)
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
public static<T> Stream<T> generate(Supplier<T> s) //案例
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream21 = Stream.iterate(2, x -> x + 2).limit(3); //2 4 6
//斐波那契数列:1 1 2 3 5 8
Stream<Integer> stream22 = Stream.iterate(new int[]{1, 1}, n -> new int[]{n[1], n[0] + n[1]}).limit(6).map(n -> n[0]);
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);

(4)BufferedReader

//BufferedReader 类接口
public Stream<String> lines() //案例
BufferedReader reader = new BufferedReader(new FileReader("G:\\stream.txt"));
Stream<String> lineStream = reader.lines();

(5)Pattern

//Pattern 类接口
public Stream<String> splitAsStream(final CharSequence input) //案例
Pattern pattern = Pattern.compile("-");
Stream<String> stream = pattern.splitAsStream("a-b-c-d");

3 Stream 的中间操作

(1)主要接口

//过滤
Stream<T> filter(Predicate<? super T> predicate)
//去重
Stream<T> distinct()
//跳过 n 个元素
Stream<T> skip(long n)
//限制元素个数
Stream<T> limit(long maxSize)
//排序
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
//映射
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
//消费
Stream<T> peek(Consumer<? super T> action)

(2)案例

Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
stream.filter(e -> e > 2 && e < 8) //4 5 5 7 3 6
.distinct() //4 5 7 3 6
.skip(1) //5 7 3 6
.limit(3) //5 7 3
.sorted((o1, o2) -> o2 - o1) //7 5 3
.map(e -> e * e) //49 25 9
.forEach(System.out::println);

4 Stream 的终端操作

(1)主要接口

void forEach(Consumer<? super T> action) //遍历所有元素

Optional<T> min(Comparator<? super T> comparator) //最小值
Optional<T> max(Comparator<? super T> comparator) //最大值
long count(); //元素个数 boolean allMatch(Predicate<? super T> predicate) //判断是否全匹配
boolean noneMatch(Predicate<? super T> predicate) //判断是否全不匹配
boolean anyMatch(Predicate<? super T> predicate) //判断是否部分匹配 Optional<T> findFirst() //首元素
Optional<T> findAny() //顺序流时为首元素,并行流为访问的第一个元素 //规约运算,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<T> reduce(BinaryOperator<T> accumulator)
//规约运算,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
T reduce(T identity, BinaryOperator<T> accumulator)

(2)案例

Stream<Integer> stream = Stream.of(1, 2, 3);

Optional<Integer> min = stream.min(Integer::compare); //1
Optional<Integer> max = stream.max(Integer::compare); //3
long count = stream.count(); //3 boolean allMatch = stream.allMatch(e -> e > 2); //false
boolean noneMatch = stream.noneMatch(e -> e > 2); //false
boolean anyMatch = stream.anyMatch(e -> e > 2); //true Optional<Integer> first = stream.findFirst(); //1
Optional<Integer> any = stream.findAny(); //1 Optional<Integer> sum = stream.reduce(Integer::sum); //6
int result = stream.reduce(1, (e1, e2) -> e1 * e1 - e2 * e2); //7

5 Collectors 库

Collectors 里工具函数需配合 Stream 的 collect() 方法使用,接口如下:

<R, A> R collect(Collector<? super T, A, R> collector)
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)

(1)集合转换

List<User> list = stream.collect(Collectors.toList());
Set<User> set = stream.collect(Collectors.toSet());
Map<Integer, String> map = stream.collect(Collectors.toMap(User::getId, User::getName));
String str = stream.collect(Collectors.joining(",", "(", ")"));

(2)聚合运算

long count = stream.collect(Collectors.counting()); //元素个数
Optional<Integer> min = stream.collect(Collectors.minBy(Integer::compare)); //最小元素
Optional<Integer> max = stream.collect(Collectors.maxBy(Integer::compare)); //最大元素
Integer sumAge = stream.collect(Collectors.summingInt(User::getAge)); //元素总和
Double avg = stream.collect(Collectors.averagingDouble(User::getAge)); //元素平均值
//统计参数
DoubleSummaryStatistics statistics = stream.collect(Collectors.summarizingDouble(User::getAge));
//count: statistics.getCount()
//min: statistics.getMin()
//max: statistics.getMax()
//sum: statistics.getSum()
//average: statistics.getAverage()

(3)规约运算

//规约操作,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<Integer> sum = stream.collect(Collectors.reducing(Integer::sum));
//规约操作,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
Integer result = stream.collect(Collectors.reducing(1, (e1, e2) -> e1 * e1 - e2 * e2));

(4)分组

//单属性分组
Map<Boolean, List<User>> sexMap = stream.collect(Collectors.groupingBy(User::getSex));
//多重分组:先根据性别分组,再根据年龄分组
Map<Boolean, Map<Integer, List<User>>> sexAgeMap = stream.collect(Collectors.groupingBy(User::getSex, Collectors.groupingBy(User::getAge)));

(5)分区

Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
Map<Boolean, List<Integer>> partMap = stream.collect(Collectors.partitioningBy(e -> e > 5));
//{false=[4, 1, 5, 5, 3, 2], true=[9, 8, 7, 6]}

说明:只能分为2个区。

​ 声明:本文转自Stream 总结

Stream 总结的更多相关文章

  1. SQL Server-聚焦查询计划Stream Aggregate VS Hash Match Aggregate(二十)

    前言 之前系列中在查询计划中一直出现Stream Aggregate,当时也只是做了基本了解,对于查询计划中出现的操作,我们都需要去详细研究下,只有这样才能对查询计划执行的每一步操作都了如指掌,所以才 ...

  2. Node.js:理解stream

    Stream在node.js中是一个抽象的接口,基于EventEmitter,也是一种Buffer的高级封装,用来处理流数据.流模块便是提供各种API让我们可以很简单的使用Stream. 流分为四种类 ...

  3. node中的Stream-Readable和Writeable解读

    在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...

  4. nodejs中流(stream)的理解

    nodejs的fs模块并没有提供一个copy的方法,但我们可以很容易的实现一个,比如: var source = fs.readFileSync('/path/to/source', {encodin ...

  5. Node学习笔记(一):stream流操作

    NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...

  6. Stream

    Stream的好处 1.Stream AP的引入弥补了JAVA函数式编程的缺陷.2.Stream相比集合类占用内存更小:集合类里的元素是存储在内存里的,Stream里的元素是在访问的时候才被计算出来. ...

  7. Stream流

    在Node中,存在各式各样不同的数据流,Stream(流)是一个由不同对象实现的抽象接口.例如请求HTTP服务器的request是一个 流,类似于stdout(标准输出):包括文件系统.HTTP 请求 ...

  8. [LeetCode] Data Stream as Disjoint Intervals 分离区间的数据流

    Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...

  9. [LeetCode] Moving Average from Data Stream 从数据流中移动平均值

    Given a stream of integers and a window size, calculate the moving average of all integers in the sl ...

  10. [LeetCode] Find Median from Data Stream 找出数据流的中位数

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

随机推荐

  1. vue3 路由页面返回时,恢复滚动条位置

    首先,路由必须是KeepAlive模式 <script setup lang="ts"> import { onActivated } from "vue&q ...

  2. [转帖]在 TiDB 中正确使用索引,性能提升 666 倍

    https://tidb.net/book/tidb-monthly/2022/2022-04/usercase/index-666 背景​ 最近在给一个物流系统做TiDB POC测试,这个系统是基于 ...

  3. [转帖]TiDB 5.1 Write Stalls 应急文档

    https://tidb.net/blog/ac7174dd#4.%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E5%87%BA%E7%8E%B0%E4%BA%86%20w ...

  4. [转帖]如何使用 sed 命令删除文件中的行

    https://zhuanlan.zhihu.com/p/80212245 sed 命令是 Linux 中的重要命令之一,在文件处理方面有着重要作用.可用于删除或移动与给定模式匹配的特定行.-- Ma ...

  5. [转帖]Kafka可靠性之HW与Leader Epoch

    <深入理解Kafka:核心设计与实现原理>是基于2.0.0版本的书 在这本书中,终于看懂了笔者之前提过的几个问题 准备知识 1.leader里存着4个数据:leader_LEO.leade ...

  6. [转帖]linux块I/O总体概括

    直接先上重点,linux中IO栈的完全图如下: 系统中能够随机访问固定大小数据片的硬件设备称作块设备.固定大小的数据片称为块.常见的块设备就是硬盘了.不能随机访问的就是字符设备了,管理块设备比字符设备 ...

  7. [转帖]Linux学习14-ab报错apr_pollset_poll: The timeout specified has expired (70007)

    https://www.cnblogs.com/yoyoketang/p/10255100.html 前言 使用ab压力测试时候出现报错apr_pollset_poll: The timeout sp ...

  8. Istio安装和部署

    Istio的版本对k8s的版本是有要求的,不兼容的版本会引发一些隐蔽的错误,安装前先参考下图 版本 目前支持 发行日期 停止维护 支持的 Kubernetes 版本 未测试,可能支持的 Kuberne ...

  9. elementUI日期选择器,对日期格式进行处理

    使用elementUI日期选择器中,获取不同格式的时间 <el-form-item label="归零时间:" prop="zeroing"> &l ...

  10. elementui表格内容超出显示省略号

    有些时候表格的内容太长了: 但是elementui中的表格,会进行换行处理: 此时表格的高度就会发生变化 这样就不好看,此时就要进行省略号来出来这个问题: el-table是有这个控制属性的::sho ...