关于Stream的使用
引言
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
转自:https://blog.csdn.net/y_k_y/article/details/84633001
特点:
1 . 不是数据结构,不会保存数据。
2. 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)
3. 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。
创建流
// 获取顺序流
Stream stream = new ArrayList().stream();
// 获取并行流
Stream parallelStream = new ArrayList().parallelStream();
// 数组转成流
Integer[] nums = {1,2,3};
Stream<Integer> streamArray = Arrays.stream(nums);
赋值
// of方法直接赋值
Stream<Integer> stream1 = Stream.of(1,2,3,4,5);
stream1.forEach(System.out::println); // 1 2 3 4 5
// iterate生成生成无限顺序有序流,主要作用是抽象迭代逻辑
Stream<Integer> stream2 = Stream.iterate(2, x -> x * 2).limit(5);
stream2.forEach(System.out::println); // 2 4 8 16 32
// generate生成无限顺序无序流,其中每个元素由提供的供应商生成。这适用于生成恒定流,随机元素流等。
Stream<Integer> stream3 = Stream.generate(new Random()::nextInt).limit(2);
stream3.forEach(System.out::println); //15356208 -2042159
筛选与切片
filter:过滤流中的某些元素 limit(n):获取n个元素 skip(n):跳过n元素 distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10};
Stream<Integer> streamArray = Arrays.stream(nums);
Stream<Integer> result = streamArray
.distinct() // 去重 1 2 3 4 5 6 7 8 9 10
.filter(i -> (i > 2)) // 筛选出值>2的元素 3 4 5 6 7 8 9 10
.skip(2) // 跳过前2个元素 5 6 7 8 9 10
.limit(4); // 获取前4个元素 5 6 7 8
映射
map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10};
Stream<Integer> streamArray = Arrays.stream(nums);
List<String> strings = streamArray
.map(String::valueOf) // 通过String.valueOf()方法将各个元素转为字符串
.collect(Collectors.toList()); // 将流转为List集合
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
Stream<String> streamArray2 = Stream.of("1.2.3", "4.5.6", "7.8.9");
List<String> result = streamArray2
.flatMap(s -> Arrays.stream(s.split("\\."))) //将流中的每个值都换成另一个流,然后分割
.collect(Collectors.toList());
// 1 2 3 4 5 6 7 8 9
排序
sorted():自然排序,流中元素需实现Comparable接口
List<String> list = Arrays.asList("a", "d", "c", "b", "x");
List<String> result = list.stream()
.sorted()
.collect(Collectors.toList());
// a b c d x
sorted(Comparator com):定制排序,自定义Comparator排序器
Person s1 = new Person("aa", 10);
Person s2 = new Person("bb", 20);
Person s3 = new Person("aa", 30);
Person s4 = new Person("dd", 40);
List<Person> personList = Arrays.asList(s1, s2, s3, s4);
//自定义排序:先按姓名升序,姓名相同则按年龄升序
personList.stream().sorted(
(o1, o2) -> {
if (o1.getName().equals(o2.getName())) {
return o1.getAge() - o2.getAge();
} else {
return o1.getName().compareTo(o2.getName());
}
}
).forEach(person -> System.out.println(person.getName()));
消费
peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值
Person s1 = new Person("aa", 10);
Person s2 = new Person("bb", 20);
Person s3 = new Person("aa", 30);
Person s4 = new Person("dd", 40);
List<Person> personList = Arrays.asList(s1, s2, s3, s4);
personList.stream()
.peek(person -> person.setAge(100))
.forEach(person -> System.out.println(person.getName()+":"+person.getAge()));
匹配
allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
// 里面的元素是否都满足>10这个条件
boolean result = integers.stream().allMatch(i -> i > 10); // false
noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 里面的元素是否都 不 满足>10这个条件
boolean result = list.stream().noneMatch(i -> i > 10); // true
anyMatch:接收一个 Predicate 函数,只要流中存在元素满足该断言则返回true,否则返回false
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
// 里面的元素是否存在满足>10这个条件
boolean result = list.stream().anyMatch(i -> i > 10); // true
findFirst:返回流中第一个元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
// Optional对象常用于解决空指针问题
Optional<Integer> optional = list.stream().findFirst();
System.out.println(optional.get()); // 1
count:返回流中元素的总个数
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
Long result = list.stream().count();
System.out.println(result); // 6
max:返回流中元素最大值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
Integer max = list.stream().max(Integer::compareTo).get(); // 11
min:返回流中元素最小值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 11);
Integer min = list.stream().min(Integer::compareTo).get(); // 1
reduce
Optional<T> reduce(BinaryOperator<T> accumulator)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Optional<Integer> optional = list.stream().reduce((x1, x2) -> x1 + x2);
System.out.println(optional.get()); // 21(为流中元素的和)
// 等效于
// Optional<Integer> optional = list.stream().reduce(Integer::sum);
T reduce(T identity, BinaryOperator<T> accumulator)
identity:返回实例 accumulator:累加器
String[] strings = {"a", "b", "c", "d", "e"};
String reduce2 = Arrays.stream(strings).reduce("", (a, b) -> {
if (!"".equals(a)) {
return a + "|" + b;
} else {
return b;
}
});
/**
* 执行流程:
* 第一个元素identity的值为"",因此a的初始值为"",b的初始值为流中第一个元素"a"
* 第一次执行之后得到结果"a",然后执行结果的值赋给a,流中第二个元素的值"b"赋给b
* 第二次执行之后得到结果"a|b",然后以此类推
*/
System.out.println(reduce2); // a|b|c|d|e
reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner)
identity:返回实例 accumulator:累加器 combiner:组合器
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
Integer v2 = list.stream().reduce(0,
(x1, x2) -> {
System.out.println("stream accumulator: x1:" + x1 + " x2:" + x2);
return x1 - x2;
},
// 第三个参数---参数的数据类型必须为返回数据类型,改参数主要用于合并多个线程的result值
//(Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result)
(x1, x2) -> {
System.out.println("stream combiner: x1:" + x1 + " x2:" + x2);
return x1 * x2;
});
System.out.println(v2); // -300
关于Stream的使用的更多相关文章
- SQL Server-聚焦查询计划Stream Aggregate VS Hash Match Aggregate(二十)
前言 之前系列中在查询计划中一直出现Stream Aggregate,当时也只是做了基本了解,对于查询计划中出现的操作,我们都需要去详细研究下,只有这样才能对查询计划执行的每一步操作都了如指掌,所以才 ...
- Node.js:理解stream
Stream在node.js中是一个抽象的接口,基于EventEmitter,也是一种Buffer的高级封装,用来处理流数据.流模块便是提供各种API让我们可以很简单的使用Stream. 流分为四种类 ...
- node中的Stream-Readable和Writeable解读
在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...
- nodejs中流(stream)的理解
nodejs的fs模块并没有提供一个copy的方法,但我们可以很容易的实现一个,比如: var source = fs.readFileSync('/path/to/source', {encodin ...
- Node学习笔记(一):stream流操作
NodeJs中谈及较多的可能就是Stream模块了,先写一个简单的ajax回调 $.post("index.php",{data:'aaa',order:'ccc'},functi ...
- Stream
Stream的好处 1.Stream AP的引入弥补了JAVA函数式编程的缺陷.2.Stream相比集合类占用内存更小:集合类里的元素是存储在内存里的,Stream里的元素是在访问的时候才被计算出来. ...
- Stream流
在Node中,存在各式各样不同的数据流,Stream(流)是一个由不同对象实现的抽象接口.例如请求HTTP服务器的request是一个 流,类似于stdout(标准输出):包括文件系统.HTTP 请求 ...
- [LeetCode] Data Stream as Disjoint Intervals 分离区间的数据流
Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...
- [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 ...
- [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.base64÷4
666C61677B45333342374644384133423834314341393639394544444241323442363041417D 根据题目base64÷4得base16 在线工 ...
- 如何系统学习C 语言(上)之 基础篇
大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...
- Des加密解密(公共方法)
1 public class Des 2 { 3 public static string Encrypt(string message, string key) 4 { 5 DES des = ne ...
- i love dingning
"如果你爱一个人,不是下课给人家买买水,不是短信发来发去,也不是周末一起出来唱唱歌聊聊天吃吃饭,而是做一个出色的人.以后的以后,可能还有别的人爱她,你要做的,是把别人都比下去.你要变得优秀, ...
- 算法学习->求解三角形最小路径及其值
00 问题 00-1 描述 对给定高度为n的一个整数三角形,找出从顶部到底部的最小路径和.每个整数只能向下移动到与之相邻的整数. 找到一个一样的力扣题:120. 三角形最小路径和 - 力扣(LeetC ...
- 区块链开发学习第三章:私有链上部署helloBlockchain简单合约
前面讲了部署私有链以及新增账户,现在进行到了部署合约了,此操作真是踩了无数无数无数的坑,到写文章为止确实是已经部署好了,但是还有些坑是还没有解决的! 一.Solidity编译器 开始的时候用的http ...
- node 中第三方模块的加载过程原理
node 中第三方模块的加载过程原理 凡是第三方模块都必须通过 npm 来下载 使用的时候就可以通过require('包名') 的方式来进行加载才可以使用 不可能有任何一个第三方包和核心模块的名字是一 ...
- MacOS升级到Monterey后python SSL握手失败问题
MacOS升级到Monterey 12.0.1后,忽然发现原来工作正常的python3请求华为restconf API报错失败,提示 ssl.SSLError: [SSL: SSLV3_ALERT_H ...
- CCCC-exercise
CCCC-exercise 1.L1 总结L1 1-27里面我觉得有东西可以总结的题目 贴了部分的代码 L1-006(20) 一个正整数 N 的因子中可能存在若干连续的数字.例如 630 可以分解为 ...
- [cf1392H]ZS Shuffles Cards
考虑统计每一轮(以抽到小丑为一轮)的贡献,不难发现答案即期望轮数*每轮期望次数 关于期望轮数,当前牌堆里已经在$S$中的卡实际上没有意义,不妨将这一类卡从牌堆中删除 此时,定义$f_{i}$表示$S$ ...