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. 【TouchGFX】IAR 下实现 touchgfx Caching Bitmaps 通过文件方式获取图像资源

    1.Caching Bitmaps 修改缓存方式 2.修改 blockCopy 方法(注意:忘记返回状态导致发生错误) 3.修改分散文件将位于 ExtFlashSection section 数据重定 ...

  2. 【C++】类成员冒号初始化以及构造函数内赋值

    From:https://blog.csdn.net/zj510/article/details/8135556 通常我们对类成员进行"初始化"有两种方式: 1. 构造函数后面跟冒 ...

  3. 神经网络优化篇:详解局部最优的问题(The problem of local optima)

    局部最优的问题 在深度学习研究早期,人们总是担心优化算法会困在极差的局部最优,不过随着深度学习理论不断发展,对局部最优的理解也发生了改变.向展示一下现在怎么看待局部最优以及深度学习中的优化问题. 这是 ...

  4. [java] - 获取上传到服务器上的文件路径

    request.getSession().getServletContext().getRealPath("upload/" );

  5. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.11.17)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  6. [转帖]Linux 性能监控 Sar (Sysstat) 示例

    https://bbs.huaweicloud.com/blogs/345343#   [摘要] 使用 sar,您可以实时监控各种 Linux 子系统(CPU.内存.I/O..)的性能,还可以持续收集 ...

  7. [转帖]Percolator - 分布式事务的理解与分析

    https://zhuanlan.zhihu.com/p/261115166 Percolator - 分布式事务的理解与分析 概述 一个web页面能不能被Google搜索到,取决于它是否被Googl ...

  8. [转帖]华为FusionSphere虚拟化解决方案介绍

    https://huaweicloud.csdn.net/63566589d3efff3090b5d243.html?spm=1001.2101.3001.6650.2&utm_medium= ...

  9. [转帖]kubelet 原理解析三:runtime

    本文转自:https://feisky.xyz/posts/kube... 架构 Kubelet 架构图 Generic Runtime Manager:这是容器运行时的管理者,负责于 CRI 交互, ...

  10. [转帖]接口偶尔超时,竟又是JVM停顿的锅!

    https://www.cnblogs.com/codelogs/p/16391159.html 简介# 继上次我们JVM停顿十几秒的问题解决后,我们系统终于稳定了,再也不会无故重启了!这是之前的文章 ...