引言

  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. 主集天线和分集天线——4G天线技术

    主集天线和分集天线 分集接收技术是一项主要的抗衰落技术,可以大大提高多径衰落信道传输下的可靠性,在实际的移动通信系统中,移动台常常工作在城市建筑群或其他复杂的地理环境中,而且移动的速度和方向是任意的. ...

  2. stm32f103系列引脚定义-功能图

    器件功能和配置(STM32F103xx增强型) STM32F103xx增强型模块框架图 STM32F103xx增强型VFQFPN36管脚图 STM32F103xx增强型LQFP100管脚图 STM32 ...

  3. 【代码更新】单细胞分析实录(20): 将多个样本的CNV定位到染色体臂,并画热图

    之前写过三篇和CNV相关的帖子,如果你做肿瘤单细胞转录组,大概率看过: 单细胞分析实录(11): inferCNV的基本用法 单细胞分析实录(12): 如何推断肿瘤细胞 单细胞分析实录(13): in ...

  4. 对SQLServer错误使用聚集索引的优化案例(千万级数据量)

    前言: 半个月前发了文章 SQLServer聚集索引导致的插入性能低 终于等到生产环境休整半天,这篇文章是对前文的实际操作. 以下正文开始: 异常:近期发现偶尔有新数据插入超时. 分析:插入条码有多种 ...

  5. Python中Numpy及Matplotlib使用

    Python中Numpy及Matplotlib使用 1. Jupyter Notebooks 作为小白,我现在使用的python编辑器是Jupyter Notebook,非常的好用,推荐!!! 你可以 ...

  6. 51nod_1003 阶乘后面0的数量(求N!中5的个数,数论)

    题意: n的阶乘后面有多少个0? 6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0.   Input 一个数N(1 <= N <= 10^9) OutPut 输出0的数 ...

  7. 浅议NetMQ常见模式和消息加密机制

    浅议NetMQ常见模式和消息加密机制 概述 在传统企业级开发中,消息队列机制已经成为一种非常常见的技术实现手段,而基于NetMQ则看起来有点像一朵"奇葩",看起来从名字似乎是一个消 ...

  8. 记一次排查CPU高的问题

    背景 将log4j.xml的日志级别从error调整为info后,进行压测发现CPU占用很高达到了90%多(之前也就是50%,60%的样子). 问题排查 排查思路:  看进程中的线程到底执行的是什么, ...

  9. 线程私有数据TSD——一键多值技术,线程同步中的互斥锁和条件变量

    一:线程私有数据: 线程是轻量级进程,进程在fork()之后,子进程不继承父进程的锁和警告,别的基本上都会继承,而vfork()与fork()不同的地方在于vfork()之后的进程会共享父进程的地址空 ...

  10. MySQL到底能否解决幻读问题

    先说结论,MySQL 存储引擎 InnoDB 在可重复读(RR)隔离级别下是解决了幻读问题的. 方法:是通过next-key lock在当前读事务开启时,1.给涉及到的行加写锁(行锁)防止写操作:2. ...