引言

  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的使用的更多相关文章

  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. 2021.9.18考试总结[NOIP模拟56]

    T1 爆零 贪心地想,肯定要先走完整个子树再走下一个,且要尽量晚地走深度大的叶子.所以对每个点的儿子以子树树高为关键字排序$DFS$即可. 也可$DP$. $code:$ T1 #include< ...

  2. windows下wchar_t的问题

    使用vs新建工程或者编译工程的时候默认在编译设置里面讲wchar_t设置为内置类型,如下图: 但是在编译相互依赖的工程的时候,如果有的工程不将wchar_t设置为内置类型的时候,将会出现链接错误,需要 ...

  3. Linux修改bashrc

    .bashrc是一个隐藏的文件,要打开并修改该文件需要: (1) 查看:ll -a 找到文件 .bashrc: (2) 打开:vi .bashrc (或者 vim .bashrc) 打开文件: (3) ...

  4. $.ajax、$.get和$.post方法成功,完成请求,错误或失败的回调

    一.$.get和$.post的不同    1.get通过url提交的,post是通过http消息实体提交的    2.get提交大小限制为2kb,post不限制    3.get提交会被缓存下来,有安 ...

  5. SkyWalking部署及.Net Core简单使用

    SkyWalking官方网站非常详细,以下只是本人学习过程的整理 一.SkyWalking简介 1.概念 SkyWalking是分布式系统的应用程序性能监视工具,专为微服务.云原生架构而设计 SkyW ...

  6. Python小练习之验证“哥德巴赫猜想”

    设计内容:任何一个大于2的偶数都可以分解为两个素数之和,这就是著名的哥达巴赫猜想. 设计要求:要求输入一个大于2的偶数,程序运行后,输出两个素数,其和正好等于该偶数. 1.    实验代码(知道是你们 ...

  7. Linux 用户&用户组

    用户和用户组的概念 用户 ---> 使用操作系统的人 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系 ...

  8. linux运维思想

    1.安装部署某个服务或者研究某个知识点时,宁可花大量时间,也需要尽量将该服务搞透,后续再遇到相关问题时你会发现这为你节省的时间将远远比你当时花的时间多. 2.安装部署时,做好记录,发本地记录并发表博文 ...

  9. ArrayList 源码分析和自定义ArrayList实现

    概述 ArrayList 是基于数组实现的,是一个能自动扩展的动态数组. ArrayList 是线程不安全的,多线程情况下添加元素会出现数组越界的情况,而且数组赋值操作不是原子操作,会导致多线程情况下 ...

  10. 开发规范 - UML图

    依赖关系是用一套带箭头的虚线表示,他通常描述一个对象在运行期间会用到另一个对象的关系.如图为例码农只有在工作的时候才会用到 Mac 电脑,所以这种依赖关系是依赖于运行状态的.通常情况下是在程序里面通过 ...