首页 > 其他分享 >Stream 总结

Stream 总结

时间:2023-03-19 16:58:37浏览次数:49  
标签:总结 Stream stream Collectors collect Optional e2

1 前言

Stream 是 Java 8 中为方便操作集合及其元素而定制的接口,它将要处理的元素集合看作一种流,对流中的元素进行过滤、排序、映射、聚合等操作。使用 Stream API,就好像使用 SQL 中的 select 语句操作数据库,非常快捷高效,一行代码可以实现很多功能。

(1)Stream 操作分类

  • 中间操作:每次操作返回一个新的 Stream 对象(主要操作有:filter、map、sorted、peek、distinct、limit、skip 等)。
  • 终端操作:每次操作返回一个值或集合,每个流只能进行一次终端操作(主要操作有:forEach、max、min、count、reduce、collect、anyMatch、allMatch、findFirst、findAny 等)。

(2)Stream 特性

  • 不存储数据:Stream 不是数据结构,不存储数据,只提供了一系列操作数据的接口。
  • 不改变数据源:终端操作后会产生一个新的值或集合。
  • 延迟执行:只有调用终端操作时,中间操作才会执行。

在学习 Stream 之前,需要先掌握 Lambda 表达式和 Optional,详见→Lambda 表达式总结Optional 详解

2 Stream 的创建

(1)Collection

//Collection 类接口
default Stream<E> stream() //顺序流
default Stream<E> parallelStream() //并行流

//案例
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流

说明:List 和 Set 是 Collection 的子类。

(2)Arrays

//Arrays 类接口
public static <T> Stream<T> stream(T[] array)

//案例
Integer[] nums = new Integer[10]{8, 2, 5, 6};
Stream<Integer> stream = Arrays.stream(nums);

(3)Stream

//Stream 类接口
public static<T> Stream<T> of(T... values) //Arrays.stream(values)
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
public static<T> Stream<T> generate(Supplier<T> s)

//案例
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream21 = Stream.iterate(2, x -> x + 2).limit(3); //2 4 6
//斐波那契数列:1 1 2 3 5 8
Stream<Integer> stream22 = Stream.iterate(new int[]{1, 1}, n -> new int[]{n[1], n[0] + n[1]}).limit(6).map(n -> n[0]);
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);

(4)BufferedReader

//BufferedReader 类接口
public Stream<String> lines()

//案例
BufferedReader reader = new BufferedReader(new FileReader("G:\\stream.txt"));
Stream<String> lineStream = reader.lines();

(5)Pattern

//Pattern 类接口
public Stream<String> splitAsStream(final CharSequence input)

//案例
Pattern pattern = Pattern.compile("-");
Stream<String> stream = pattern.splitAsStream("a-b-c-d");

3 Stream 的中间操作

(1)主要接口

//过滤
Stream<T> filter(Predicate<? super T> predicate)
//去重
Stream<T> distinct()
//跳过 n 个元素
Stream<T> skip(long n)
//限制元素个数
Stream<T> limit(long maxSize)
//排序
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
//映射
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
//消费
Stream<T> peek(Consumer<? super T> action)

(2)案例

Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
stream.filter(e -> e > 2 && e < 8) //4 5 5 7 3 6
	  .distinct() //4 5 7 3 6
	  .skip(1) //5 7 3 6
	  .limit(3) //5 7 3
	  .sorted((o1, o2) -> o2 - o1) //7 5 3
	  .map(e -> e * e) //49 25 9
	  .forEach(System.out::println);

4 Stream 的终端操作

(1)主要接口

void forEach(Consumer<? super T> action) //遍历所有元素

Optional<T> min(Comparator<? super T> comparator) //最小值
Optional<T> max(Comparator<? super T> comparator) //最大值
long count(); //元素个数

boolean allMatch(Predicate<? super T> predicate) //判断是否全匹配
boolean noneMatch(Predicate<? super T> predicate) //判断是否全不匹配
boolean anyMatch(Predicate<? super T> predicate) //判断是否部分匹配

Optional<T> findFirst() //首元素
Optional<T> findAny() //顺序流时为首元素,并行流为访问的第一个元素

//规约运算,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<T> reduce(BinaryOperator<T> accumulator)
//规约运算,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
T reduce(T identity, BinaryOperator<T> accumulator)

(2)案例

Stream<Integer> stream = Stream.of(1, 2, 3);

Optional<Integer> min = stream.min(Integer::compare); //1
Optional<Integer> max = stream.max(Integer::compare); //3
long count = stream.count(); //3

boolean allMatch = stream.allMatch(e -> e > 2); //false
boolean noneMatch = stream.noneMatch(e -> e > 2); //false
boolean anyMatch = stream.anyMatch(e -> e > 2); //true

Optional<Integer> first = stream.findFirst(); //1
Optional<Integer> any = stream.findAny(); //1

Optional<Integer> sum = stream.reduce(Integer::sum); //6
int result = stream.reduce(1, (e1, e2) -> e1 * e1 - e2 * e2); //7

5 Collectors 库

Collectors 里工具函数需配合 Stream 的 collect() 方法使用,接口如下:

<R, A> R collect(Collector<? super T, A, R> collector)
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)

(1)集合转换

List<User> list = stream.collect(Collectors.toList());
Set<User> set = stream.collect(Collectors.toSet());
Map<Integer, String> map = stream.collect(Collectors.toMap(User::getId, User::getName));
String str = stream.collect(Collectors.joining(",", "(", ")"));

(2)聚合运算

long count = stream.collect(Collectors.counting()); //元素个数
Optional<Integer> min = stream.collect(Collectors.minBy(Integer::compare)); //最小元素
Optional<Integer> max = stream.collect(Collectors.maxBy(Integer::compare)); //最大元素
Integer sumAge = stream.collect(Collectors.summingInt(User::getAge)); //元素总和
Double avg = stream.collect(Collectors.averagingDouble(User::getAge)); //元素平均值
//统计参数
DoubleSummaryStatistics statistics = stream.collect(Collectors.summarizingDouble(User::getAge));
//count: statistics.getCount()
//min: statistics.getMin()
//max: statistics.getMax()
//sum: statistics.getSum()
//average: statistics.getAverage()

(3)规约运算

//规约操作,定义运算 o, result = ((((e1 o e2)) o e3) o e4) o ...
Optional<Integer> sum = stream.collect(Collectors.reducing(Integer::sum));
//规约操作,定义运算 o, result = ((((identity o e1)) o e2) o e3) o ...
Integer result = stream.collect(Collectors.reducing(1, (e1, e2) -> e1 * e1 - e2 * e2));

(4)分组

//单属性分组
Map<Boolean, List<User>> sexMap = stream.collect(Collectors.groupingBy(User::getSex));
//多重分组:先根据性别分组,再根据年龄分组
Map<Boolean, Map<Integer, List<User>>> sexAgeMap = stream.collect(Collectors.groupingBy(User::getSex, Collectors.groupingBy(User::getAge)));

(5)分区

Stream<Integer> stream = Stream.of(4, 9, 1, 8, 5, 5, 7, 3, 6, 2);
Map<Boolean, List<Integer>> partMap = stream.collect(Collectors.partitioningBy(e -> e > 5));
//{false=[4, 1, 5, 5, 3, 2], true=[9, 8, 7, 6]}

说明:只能分为2个区。

​ 声明:本文转自Stream 总结

标签:总结,Stream,stream,Collectors,collect,Optional,e2
From: https://www.cnblogs.com/zhyan8/p/17232796.html

相关文章

  • 十大排序总结
    Introduction​ 本篇是对十大排序的总结,会涉及每个排序的重要步骤、时间复杂度、空间复杂度、稳定性、代码实现Summary排序算法最差时间复杂度空间复杂度平均时......
  • 今日总结
    上午学了几个小时编程,中午去买了日抛,下午上了课,去练习设计动作了,晚上徒步从长安公园走了近五公里回到了学校,但是去吃了自助餐陪女朋友,逃了礼仪队的训练。希望不会被弄死。......
  • Lambda 表达式总结
    1Lambda表达式简介​Lambda表达式是JDK8的新特性,主要用于简化匿名内部类的定义,帮助用户方便、高效地书写优雅的代码。​Lambda表达式实现的必须是一个接......
  • adb常用命令总结
    1前言​ADB(AndroidDebugBridge)即Android调试桥,采用监听SocketTCP端口的方式通讯。连接手机有2种方式:有线连接、无线连接。​(1)有线连接​使用数据线......
  • numpy数组初始化方法总结
    1使用list初始化a=np.array([[1,2,3],[4,5,6]],dtype='float32')#a=[[1.2.3.],[4.5.6.]]2赋值与复制(1)赋值a=np.array([1,2,3])b=aprint(bisa)#Trueb[0]......
  • 【RPC高性能框架总结】5.高性能nio框架netty(中)
    接上一篇《​​4.高性能nio框架netty(上)​​》上一篇我们编写了使用Netty框架开发的客户端的启动类“NettyTestClient”以及业务处理类“NettyTestClientHandler”,本篇我......
  • 【Docker学习总结】8.Docker-查看和删除镜像
    上一篇技术总结,我们使用常用的Docker命令创建了容器,并在容器中搭建了Nginx环境、部署了一个静态网页,并成功在宿主机中访问容器中的静态网页,以及使用浏览器在宿主机映射容器......
  • 【Java邮件开发】3.邮件协议总结与邮件服务器的工作原理
    我们来对邮件协议进行总结,并探讨邮件服务器的工作原理一、邮件协议剖析1.指令过程描述记得上一篇总结,我们手动敲指令发邮件的时候,登录smtp服务器的......
  • 李沐多模态串讲视频总结 ALBEF VLMo BLIP CoCa BEITv3 模型简要介绍
    开场多模态串讲的上篇是比较传统的多模态任务多模态最后的模态交互很重要传统的缺点是都用了预训练的目标检测器,训练和部署都很困难。ViLT把预训练的目标检......
  • Git常用命令总结
    1简介Git是一个开源的分布式版本控制系统,最初由LinusTorvalds为管理Linux内核而开发的开源软件,目前已应用在windows等操作系统上。SVN也是一种版本控制系统,但......