StreamAPI
一、简介
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作 。
Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。
通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。
(Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。)
常见Stream Source生成方式
数据和集合获取
1)Collection.stream()
2)Collection.parallelStream()
3)Arrays.stream(T array) or Stream.of()
BufferedReader获取
java.io.BufferedReader.lines()
Stream常用操作
Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
二、Stream使用样例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.Test;
import org.mockito.internal.matchers.CompareTo; public class StreamTest { /**
* 构造流的几种常见方法
*/
@Test
public void createStream() { // 通过数组获取Stream
String[] strs = new String[] { "a", "b", "c" };
Stream<String> s1 = Stream.of(strs);
Stream<String> s2 = Arrays.stream(strs);
Stream<String> s3 = Stream.of("a", "b", "c");
// 通过集合
List<String> strLists = Arrays.asList("a", "b", "c");
Stream<String> s4 = strLists.stream(); // 需要注意的是,对于基本数值型,目前有三种对应的包装类型 Stream:
// IntStream、LongStream、DoubleStream。当然我们也可以用 Stream<Integer>、Stream<Long>
// >、Stream<Double>,
// 但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream。
IntStream.of(new int[] { 1, 2, 3 }).forEach(System.out::println);
IntStream.range(1, 3).forEach(System.out::println);
IntStream.rangeClosed(1, 3).forEach(System.out::println);
} /**
* 流转换为其它数据结构
*/
@Test
public void streamToOther() {
// 转换成Array
Stream<String> s1 = Stream.of("a", "b", "c");
String[] strArray = s1.toArray(String[]::new);
// 转换成Collection
Stream<String> s2 = Stream.of("a", "b", "c");
List<String> list1 = s2.collect(Collectors.toList());
Stream<String> s3 = Stream.of("a", "b", "c");
List<String> list2 = s3.collect(Collectors.toCollection(ArrayList<String>::new));
Stream<String> s4 = Stream.of("a", "b", "c", "c");
Set<String> set1 = s4.collect(Collectors.toSet());
Stream<String> s5 = Stream.of("a", "b", "c");
Stack stack1 = s5.collect(Collectors.toCollection(Stack::new));
// 转换成String
Stream<String> s6 = Stream.of("a", "b", "c");
String str = s6.collect(Collectors.joining()).toString();
} /**
* Stream常用操作
*/
@Test
public void streamOperate() { // map 转换大写
Arrays.asList("lucy", "mark", "zhangsan").stream().map(String::toUpperCase)
.forEach(w -> System.out.println(w));
// map 求平方
Arrays.asList(1, 2, 5, 9).stream().map(n -> n * n).forEach(w -> System.out.println(w)); // flatMap 把 input Stream 中的层级结构扁平化.map是1对1,当有1对多的时候可以用flatMap转换成1对1
// 下面最终的stream 中只有数字了,flatMap把List打散
Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9))
.flatMap(s -> s.stream()).forEach(System.out::print); // filter 对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。
// 过滤小于等于3的数据
Stream.of(1, 2, 3, 4, 5, 6).filter(n -> n > 3).forEach(System.out::print); // forEach 方法接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式
// forEach 是 terminal 操作.即执行该Stream就被消费掉了,不可以再使用
Stream.of(1, 2, 3, 4, 5, 6).forEach(System.out::print); // peek 对每个元素执行操作并返回一个新的 Stream
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList()); //findFirst 它总是返回 Stream 的第一个元素
Stream.of(1, 2, 3, 4, 5, 6).findFirst().ifPresent(System.out::println); //这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则,
//和前面 Stream 的第一个、第二个、第 n 个元素组合。
//从这个意义上说,字符串拼接、数值的 sum、min、max、average 都是特殊的 reduce
//也有没有起始值的情况,这时会把 Stream 的前面两个元素组合起来,返回的是 Optional。
//求和(有初始值)
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(0,(a,b) -> a+b));
//求和(无初始值)
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).reduce(Integer::sum).get());
//拼接字符串
System.out.println(Stream.of("a","b","c").reduce("",String::concat));
// 求最小值,minValue = -3.0
System.out.println(Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min)); //limit/skip limit 返回 Stream 的前面 n 个元素;skip 则是扔掉前 n 个元素
Stream.of(1, 2, 3, 4, 5, 6).limit(3).forEach(System.out::println);
Stream.of(1, 2, 3, 4, 5, 6).skip(3).forEach(System.out::println); //sorted:对 Stream 的排序通过 sorted 进行,它比数组的排序更强之处在于你可以首先对 Stream
//进行各类 map、filter、limit、skip
//甚至 distinct 来减少元素数量后,再排序,这能帮助程序明显缩短执行时间。
//根据字符串长度排序
Stream.of("one", "two", "three", "four").sorted((w1,w2) -> w1.length()-w2.length())
.forEach(System.out::println); //Match
//allMatch:Stream 中全部元素符合传入的 predicate,返回 true
//anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true
//noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
//它们都不是要遍历全部元素才能返回结果。例如 allMatch 只要一个元素不满足条件,
//就 skip 剩下的所有元素,返回 false。
//判断数组里是否有大于9的数据
System.out.println(Stream.of(1, 2, 3, 4, 5, 6).allMatch(n -> n>9)); //java.util.stream.Collectors 类的主要作用就是辅助进行各类有用的 reduction 操作,
//例如转变输出为 Collection,把 Stream 元素进行归组。
class Person{
public Person(String name,int age) {
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
} }
// 按年龄分组
List<Person> persons = Arrays.asList(new Person("1",1),
new Person("1",1),new Person("1",2),new Person("1",3));
Map<Integer, List<Person>> personGroup = persons.stream()
.collect(Collectors.groupingBy(Person::getAge));
personGroup.keySet().stream().forEach(w -> System.out.println(personGroup.get(w)));
} }
参考资料:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
StreamAPI的更多相关文章
- Lambda学习---StreamApi使用
package com.zx; import com.zx.entity.Book; import org.junit.Test; import java.time.LocalDate; import ...
- Java8新特性——StreamAPI(二)
1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...
- Java8新特性——StreamAPI(一)
1. 流的基本概念 1.1 什么是流? 流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合. 众所周知,集合操作非常麻烦,若要对集合进行筛选.投影,需要写大量的代码, ...
- jdk8中的StreamAPI
1.实体类 package com.zy.model; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.D ...
- 项目记事【StreamAPI】:使用 StreamAPI 简化对 Collection 的操作
最近项目里有这么一段代码,我在做 code-review 的时候,觉得可以使用 Java8 StreamAPI 简化一下. 这里先看一下代码(不是源码,一些敏感信息被我用其他类替代了): privat ...
- Java8新特性——StreamAPI 的使用
StreamAPI的说明 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的 ...
- 关于Java8:StreamAPI的一点记录
关于 Stream ,Functional Interface 的一点记录 stream对于集合操作的便捷度提升: import java.util.ArrayList; import java.ut ...
- 使用java8的StreamAPI对集合计算进行代码重构
方法: 查询出所有部门成员中年龄大于30的员工姓名 部门对象: 员工对象: 模拟数据: private static List<Dept> list=new ArrayList<De ...
- 二、StreamAPI
一.Stream是什么? 是数据通道,用于操作数据源(集合.数组等)所生成的元素序列.集合讲的是数据,流讲的是计算. 注意: Stream不会存储元素. Stream不会改变源对象.相反,他们会返回一 ...
- jdk8 StreamApi
List<User> userList=new ArrayList<>(); userList.add(User.builder().age().name()).build() ...
随机推荐
- MinkowskiEngine基准测试
MinkowskiEngine基准测试 介绍卷积层和小型U网络的前馈和后馈通过时间.可以将具有相同张量步幅,步幅和内核偏移的内核映射重新用于其他层,可以在大型nueral网络中使用的所有层上,分摊此页 ...
- VRRP协议的原理与配置
VRRP出现的原因: 局域网中的用户终端通常采用配置一个默认网关的形式访问外部网络,如果此时默认网关设备发生故障,将中断所有用户终端的网络访问,这很可能会给用户带来不可预计的损失. VRRP的优点: ...
- UF_TRNS 变换相关
Open C uf5940uf5941uf5942 矩阵乘积变换uf5943 平移变换uf5944 缩放变换uf5945 旋转变换uf5946 镜像变换uf5947 实现变换,根据变换矩阵 ...
- 【NX二次开发】Block UI NXOpen::BlockStyler::BlockDialog
定义: NXOpen::BlockStyler::BlockDialog* theDialog; theDialog->PerformApply();//执行应用并重新启动对话框. theDia ...
- 从1+1=2来理解Java字节码从1+1=2来理解Java字节码
编译"1+1"代码 首先我们需要写个简单的小程序,1+1的程序,学习就要从最简单的1+1开始,代码如下: 写好java类文件后,首先执行命令javac TestJava.java ...
- SpringBoot线程池的创建、@Async配置步骤及注意事项
最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...
- 浏览Github必备的5款神器级别的Chrome插件
我们知道 Github 是程序员特有的宝藏,也可以称它为 GayHub, 大家浏览 Github 的时候,一定遇到过下面这些问题: 不克隆到本地的情况下阅读代码困难. 无法单独下载仓库中的某个文件/文 ...
- 数位dp从会打模板到不会打模板
打了几个数位$dp$,发现自己除了会打模板之外没有任何长进,遇到非模板题依然什么都不会 那么接下来这篇文章将介绍如何打模板(滑稽) 假设我们要处理$l----r$ 采用记忆化搜索的方式,枚举$< ...
- springboot+kurento+coturn+contos的视频通讯服务搭建
springboot+kurento+coturn+contos的视频通讯服务搭建 服务器CentOS Linux release 7.9.2009 (Core) 本案例成功于20210628 1.默 ...
- 【Python】(六)Python数据类型-列表和元组,九浅一深,用得到
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文分十个章节介绍数据类型中的列表(list)和元组(tuple),从使用说到底层实现,包您满意 干货满满,建议收藏,需要用到时常看看. 小伙伴们 ...