Java Stream流
Java8 Stream流编程
Stream 使用一种类似于SQL语句从数据库查询数据的直观方式来提供对 Java 集合运算和表达的高阶抽象。得益于 Lambda 所带来的函数式编程,Stream API 可以极大的提高 Java 程序员的生产力。关于函数式编程可以查看我的另一篇博客 Java 函数式接口。
什么是 Stream 流
A sequence of elements supporting sequential and parallel aggregate operations.
翻译过来就是一个支持串行和并行聚合操作的元素序列:
- 序列中的元素是一个特定类型的对象,Stream 本身并不会存储任何元素,而是按需计算
- 序列的来源可以是集合、数组、I/O channel等
- 聚合操作是类似 SQL 语句的操作,如 fiter, map, distinct, sorted 等
获取 Stream 流
- stream():创建串行流
- parallelStream():创建并行流
Java 数组
// 基本类型数组,使用 Arrays.stream() 获取流,类似的还有 LongStream, DoubleStream
int[] nums = {1, 2, 3}
IntStream intStream = Arrays.stream(arr);
// 对象类型数组,使用 Stream.of() 获取流
String[] array = {"a", "b", "c"};
// Stream.of() 内部还是调用的 Arrays.stream(T[] values)
Stream<String> stream = Stream.of(array);
Java 集合
// 集合类型获取串行流
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();
// 集合类型获取并行流
// 方法一:直接获取
// 方法二:从串行流转换
Stream<Integer> parallelStream = list.parallelStream();
Stream<Integer> parallelStream = list.stream().parallel();
Set<Integer> set = new HashSet<>();
Stream<Integer> stream2 = set.stream();
Stack<Integer> stack = new Stack<>();
Stream<Integer> stream3 = stack.stream();
Java Map
Map<String, String> map = new HashMap<>();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.valueSet().stream();
Java Stream 的使用
数组元素求和
// 传统做法
int[] nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : nums) {
sum += nums;
}
// 使用 Stream 求和
int sum = Arrays.stream(nums).sum();
集合遍历过滤
List<String> list = new ArrayList<>();
list.add("ab");
list.add("abc");
list.add("aefg");
list.add("hijkl");
// 传统方法
List<String> startWithA = new ArrayList<>();
for (String temp : list) {
if (temp.startsWith("a")) {
startWithA.add(temp);
}
}
List<String> longList = new ArrayList<>();
for (String temp : startWithA) {
if (temp.length() >= 4) {
longList.add(temp);
}
}
// Stream 方法
List<String> filtered = list.stream().filter(s -> s.startsWith("a"))
.filter(s -> s.length() >= 4)
.collect(Collectors.toList());
Stream 风格可以使得 Java 代码干净、简洁,这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理。
从上面的例子可以看出 Stream 操作有以下两个特征:
- 中间操作会返回流对象本身,多个操作可以串联成一个管道,如同流式风格
- 传统集合遍历都是通过迭代器或者For-Each的方式在集合外部进行迭代,Stream 提供了内部迭代的方式,通过访问者模式实现
Java Stream 常用方法分析
filter() 方法
将 Stream 流转换成一个子集流。
/**
* Returns a stream consisting of the elements of this stream
* that match the given predicate.
*/
Stream<T> filter(Predicate<? super T> predicate);
// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);
// 子集流中包括元素 "def", "ghij"
Stream<String> subStream = stream.filter(s -> s.length() >= 3);
map() 方法
将 Stream 流中的元素映射到另一个流中。
/**
* Returns a stream consisting of the results of applying the given
* function to the elements of this stream.
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);
// 流中包括array每个字符串的长度,{1, 2, 3, 4}
Stream<Integer> mapStream = stream.map(s -> s.length());
distinct() 方法
对 Stream 流中的元素做去重处理。
/**
* Returns a stream consisting of the distinct elements (according to
* {@link Object#equals(Object)}) of this stream.
*/
Stream<T> distinct();
// Example
String[] array = {"a", "bc", "def", "bc", "a"};
Stream<String> stream = Stream.of(array);
// "a", "bc" 是重复元素, distinct处理后流中只会保留一个
Stream<String> distinctStream = stream.distinct();
sorted() 方法
对 Stream 流中的元素排序。
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to natural order. If the elements of this stream are
* not{@code Comparable}, a {@code java.lang.ClassCastException} may
* be thrown when the terminal operation is executed.
*/
Stream<T> sorted();
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 流中的元素按字典顺序升序排列
// {"a", "ab", "b", "c", "cc"}
Stream<String> sortedStream = stream.sorted();
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the provided {@code Comparator}.
* 自定义排序规则
*/
Stream<T> sorted(Comparator<? super T> comparator);
// 流中的元素按长度升序排列
// {"a", "b", "c", "ab", "cc"}
Stream<String> sortedStream = stream.sorted((o1, o2) -> o1.length() - o2.length());
limit() 方法
截取流中的元素,取前 maxSize 个元素。
/**
* Returns a stream consisting of the elements of this stream,
* truncated to be no longer than {@code maxSize} in length. Stream<T>
* limit(long maxSize);
*/
Stream<T> limit(long maxSize);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 截取流中前3个元素,{"a", "cc", "ab"}
Stream<String> limitStream = stream.limit(3);
skip() 方法
跳过前 n 个元素,如果原 Stream 流中元素个数小于 n,则返回一个空的 Stream 流。
/**
* Returns a stream consisting of the remaining elements of this
* stream after discarding the first {@code n} elements of the
* stream.
* If this stream contains fewer than {@code n} elements then an
* empty stream will be returned.
*/
Stream<T> skip(long n);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 跳过流中前3个元素,返回 {"b", "c"}
Stream<String> skipStream = stream.skip(3);
// 跳过流中前5个元素,返回 {}
Stream<String> skipStream = stream.skip(3);
forEach() 方法
将每一个流元素交给 action 中的方法处理。
forEach 与 forEachOrdered
- 串行流,两者的效果一致,都是对流中的元素顺序执行
action中的操作 - 并行流,
forEach操作元素不一定按顺序执行,而forEachOrdered则保证元素按顺序执行
/**
* Performs an action for each element of this stream.
*/
void forEach(Consumer<? super T> action);
/**
* Performs an action for each element of this stream, in the
* encounter order of the stream if the stream has a defined
* encounter order.
*/
void forEachOrdered(Consumer<? super T> action);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 顺序输出流中的元素,{"a", "cc", "ab", "b", "c"}
stream.forEach(s -> System.out.println(s));
stream.forEachOrdered(s -> System.out.println(s));
toArray() 方法
返回一个数组,包含 Stream 流中的元素。
/**
* Returns an array containing the elements of this stream.
*/
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 将原Stream流中的元素去重后转换为数组
String[] array2 = (String[])stream.distinct().toArray();
min(), max() 方法
分别返回 Stream 流中最小的元素,最大的元素。
/**
* Returns the minimum element of this stream according to the
* provided.
*/
Optional<T> min(Comparator<? super T> comparator);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> min = list.stream().min((o1, o2) -> o1 - o2);
Optional<Integer> max = list.stream().max((o1, o2) -> o1 - o2);
// 1, 4
System.out.println(min.get() + ", " + max.get());
count() 方法
返回 Stream 流中元素的个数。
/**
* Returns the count of elements in this stream.
*/
long count();
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
// 4
long numbers = list.stream().count();
anyMatch() 方法
Stream 流中存在元素满足 predicate 中的约束,则返回 True。
/**
* Returns whether any elements of this stream match the provided
* predicate.
*/
boolean anyMatch(Predicate<? super T> predicate);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
boolean flag1 = list.stream().anyMatch(num -> num > 2); // True
boolean flag2 = list.stream().anyMatch(num -> num > 4); // False
allMatch() 方法
Stream 流中所有元素满足 predicate 中的约束,则返回 True。
/**
* Returns whether all elements of this stream match the provided
* predicate.
*/
boolean allMatch(Predicate<? super T> predicate);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
boolean flag1 = list.stream().allMatch(num -> num > 0); // True
boolean flag2 = list.stream().allMatch(num -> num > 2); // False
concat() 方法
合并两个 Stream 流中的元素。
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
* second stream.
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
@SuppressWarnings("unchecked")
Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
(Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
return stream.onClose(Streams.composedClose(a, b));
}
// Example
String[] s1 = {"a", "c", "e"};
String[] s2 = {"b", "d", "f"};
// {"a", "c", "e", "b", "d", "f"}
Stream.concat(Stream.of(s1), Stream.of(s2)).forEach(s -> System.out.println(s));
参考文章
[1] Java-Stream流详解
Java Stream流的更多相关文章
- 一文带你入门Java Stream流,太强了
两个星期以前,就有读者强烈要求我写一篇 Java Stream 流的文章,我说市面上不是已经有很多了吗,结果你猜他怎么说:"就想看你写的啊!"你看你看,多么苍白的喜欢啊.那就&qu ...
- 全面吃透JAVA Stream流操作,让代码更加的优雅
全面吃透JAVA Stream流操作,让代码更加的优雅 在JAVA中,涉及到对数组.Collection等集合类中的元素进行操作的时候,通常会通过循环的方式进行逐个处理,或者使用Stream的方式进行 ...
- Java Stream 流如何进行合并操作
1. 前言 Java Stream Api 提供了很多有用的 Api 让我们很方便将集合或者多个同类型的元素转换为流进行操作.今天我们来看看如何合并 Stream 流. 2. Stream 流的合并 ...
- Java Stream 流(JDK 8 新特性)
什么是 Steam Java 8 中新增了 Stream(流)来简化集合类的使用,Stream 本质上是个接口,接口中定义了很多对 Stream 对象的操作. 我们知道,Java 中 List 和 S ...
- Java | Stream流、泛型、多线程 | 整理自用
1.lambda 表达式 lambda 的延迟执行 可以对程序进行优化,尤其是使用 if {} else {} 条件判断,先判断条件是否成立,再传入计算好的参数. functionName( para ...
- 深度掌握 Java Stream 流操作,让你的代码高出一个逼格!
概念 Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选.排序.聚合等. Stream 的操作符大体上分为两种:中间操作符和终止操作符 中 ...
- Java Stream流的使用
流相关的方法可以分为三种类型,分别是:获取Stream流.中间方法.终结方法.中间方法会返回当前流,可以方便的进行链式调用. 流不可重复使用,否则会报错: java.lang.IllegalState ...
- Java Stream流排序null以及获取指定条数数据
Java8的Stream流的一些用法, //排序 carerVehEntityList = carerVehEntityList.stream().sorted( Comparator.compari ...
- Java Stream简介, 流的基本概念
在Javaor .net编程中, 我们经常见到"stream" 这个字眼. 我们大概知道这是个流的意思, 如果看完本文的话, 应该会有1个大概的概念. 一, Java中什么是St ...
- Java Stream 自定义Collector
Collector的使用 使用Java Stream流操作数据时,经常会用到各种Collector收集器来进行数据收集. 这里便深入了解一点去了解Collector的工作原理和如何自定义Collect ...
随机推荐
- echarts属性大全
// 全图默认背景 // backgroundColor: 'rgba(0,0,0,0)', // 默认色板 color: ['#ff7f50','#87cefa','#da70d6','#32cd ...
- 字符节点流--> 桥装换流
输出 存值 用法1创建字节输出节点流FileOutputStream fos = new FileOutputStream("存入文件的路径");2创建桥转换流,按照指定的字符编码 ...
- java流程控制;
一.基础阶段: 1.用户交互Scanner Scanner对象: 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入. java.uti ...
- java获取当前类的绝对路径
转自: http://blog.csdn.net/elina_1992/article/details/47419097 1.如何获得当前文件路径 常用: (1).Test.class.getRe ...
- Delphi中IdHttp调用接口,返回值乱码
--------开发环境是Delphi XE10-------- 这里要说的是BUG问题, var respStream : TStringStream; respStream.DataString有 ...
- Pytorch中tensor的打印精度
1. 设置打印精 Pytorch中tensor打印的数据长度需要使用torch.set_printoptions(precision=xx)进行设置,否则打印的长度会很短,给人一种精度不够的错觉: & ...
- [picoCTF]Scavenger Hunt write up
http://mercury.picoctf.net:5080/,这个网站周围隐藏着一些有趣的信息.你能找到它吗? 根据提示: 您应该有足够的提示来查找文件,不要运行暴力破解程序. 点击链接,进入页面 ...
- 自动化兼容性测试工具——WeTest
这个作业属于哪个课程 2021春软件工程实践|W班(福州大学) 这个作业要求在哪里 软件工程实践总结&个人技术博客 这个作业的目标 分享自动化兼容性测试工具的使用 其他参考文献 ... 目录 ...
- 基于SpringBoot WebMagic爬虫爬取大乐透双色球
大乐透网页地址:https://kjh.55128.cn/dlt-history-360.htm 双色球网页地址:https://kjh.55128.cn/ssq-history-120.htm ...
- VMwareWorkstation-安装虚拟机
安装vmware 首先就是下载VMware客户端了,Vmware是收费的,过好大多数都有破解版,或者激活码 这里我是用的是VMware16,下载在网上搜一下就有,例如 下载解压后里面有一个后缀为exe ...