阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

输出集合

275次阅读
没有评论

共计 3326 个字符,预计需要花费 9 分钟才能阅读完成。

我们介绍了 Stream 的几个常见操作:map()filter()reduce()。这些操作对 Stream 来说可以分为两类,一类是转换操作,即把一个 Stream 转换为另一个 Stream,例如map()filter(),另一类是聚合操作,即对 Stream 的每个元素进行计算,得到一个确定的结果,例如reduce()

区分这两种操作是非常重要的,因为对于 Stream 来说,对其进行转换操作 并不会触发任何计算!我们可以做个实验:

import java.util.function.Supplier; 
import java.util.stream.Stream;

public class Main {public static void main(String[] args)     {Stream<Long> s1 = Stream.generate(new NatualSupplier());
        Stream<Long> s2 = s1.map(n -> n * n);
        Stream<Long> s3 = s2.map(n -> n - 1);
        System.out.println(s3); // java.util.stream.ReferencePipeline$3@49476842
    }
}

class NatualSupplier implements Supplier<Long> {long n = 0;
    public Long get() {
        n++;
        return n;
    }
}

因为 s1 是一个 Long 类型的序列,它的元素高达 922 亿亿个,但执行上述代码,既不会有任何内存增长,也不会有任何计算,因为转换操作只是保存了转换规则,无论我们对一个 Stream 转换多少次,都不会有任何实际计算发生。

而聚合操作则不一样,聚合操作会立刻促使 Stream 输出它的每一个元素,并依次纳入计算,以获得最终结果。所以,对一个 Stream 进行聚合操作,会触发一系列连锁反应:

Stream<Long> s1 = Stream.generate(new NatualSupplier());
Stream<Long> s2 = s1.map(n -> n * n);
Stream<Long> s3 = s2.map(n -> n - 1);
Stream<Long> s4 = s3.limit(10);
s4.reduce(0, (acc, n) -> acc + n);

我们对 s4 进行 reduce() 聚合计算,会不断请求 s4 输出它的每一个元素。因为 s4 的上游是 s3,它又会向s3 请求元素,导致 s3s2请求元素,s2s1 请求元素,最终,s1Supplier 实例中请求到真正的元素,并经过一系列转换,最终被 reduce() 聚合出结果。

可见,聚合操作是真正需要从 Stream 请求数据的,对一个 Stream 做聚合计算后,结果就不是一个Stream,而是一个其他的 Java 对象。

输出为 List

reduce()只是一种聚合操作,如果我们希望把 Stream 的元素保存到集合,例如 List,因为List 的元素是确定的 Java 对象,因此,把 Stream 变为 List 不是一个转换操作,而是一个聚合操作,它会强制 Stream 输出每个元素。

下面的代码演示了如何将一组 String 先过滤掉空字符串,然后把非空字符串保存到 List 中:

import java.util.*;
import java.util.stream.*;

public class Main {public static void main(String[] args) {Stream<String> stream = Stream.of("Apple", "", null, "Pear", "  ", "Orange");
        List<String> list = stream.filter(s -> s != null && !s.isBlank()).collect(Collectors.toList());
        System.out.println(list);
    }
}

Stream 的每个元素收集到 List 的方法是调用 collect() 并传入 Collectors.toList() 对象,它实际上是一个 Collector 实例,通过类似 reduce() 的操作,把每个元素添加到一个收集器中(实际上是ArrayList)。

类似的,collect(Collectors.toSet())可以把 Stream 的每个元素收集到 Set 中。

输出为数组

把 Stream 的元素输出为数组和输出为 List 类似,我们只需要调用 toArray() 方法,并传入数组的“构造方法”:

List<String> list = List.of("Apple", "Banana", "Orange");
String[] array = list.stream().toArray(String[]::new);

注意到传入的“构造方法”是 String[]::new,它的签名实际上是IntFunction<String[]> 定义的 String[] apply(int),即传入int 参数,获得 String[] 数组的返回值。

输出为 Map

如果我们要把 Stream 的元素收集到 Map 中,就稍微麻烦一点。因为对于每个元素,添加到 Map 时需要 key 和 value,因此,我们要指定两个映射函数,分别把元素映射为 key 和 value:

import java.util.*;
import java.util.stream.*;

public class Main {public static void main(String[] args) {Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
        Map<String, String> map = stream
                .collect(Collectors.toMap(// 把元素 s 映射为 key:
                        s -> s.substring(0, s.indexOf(':')),
                        // 把元素 s 映射为 value:
                        s -> s.substring(s.indexOf(':') + 1)));
        System.out.println(map);
    }
}

分组输出

Stream还有一个强大的分组功能,可以按组输出。我们看下面的例子:

import java.util.*;
import java.util.stream.*;

public class Main {public static void main(String[] args) {List<String> list = List.of("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots");
        Map<String, List<String>> groups = list.stream()
                .collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));
        System.out.println(groups);
    }
}

分组输出使用 Collectors.groupingBy(),它需要提供两个函数:一个是分组的 key,这里使用s -> s.substring(0, 1),表示只要首字母相同的String 分到一组,第二个是分组的 value,这里直接使用Collectors.toList(),表示输出为List,上述代码运行结果如下:

{A=[Apple, Avocado, Apricots],
    B=[Banana, Blackberry],
    C=[Coconut, Cherry]
}

可见,结果一共有 3 组,按 "A""B""C" 分组,每一组都是一个List

假设有这样一个 Student 类,包含学生姓名、班级和成绩:

class Student {int gradeId; // 年级
    int classId; // 班级
    String name; // 名字
    int score; // 分数
}

如果我们有一个 Stream<Student>,利用分组输出,可以非常简单地按年级或班级把Student 归类。

小结

Stream可以输出为集合:

Stream通过 collect() 方法可以方便地输出为ListSetMap,还可以分组输出。

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计3326字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7815329
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
手把手教你,购买云服务器并且安装宝塔面板

手把手教你,购买云服务器并且安装宝塔面板

手把手教你,购买云服务器并且安装宝塔面板 前言 大家好,我是星哥。星哥发现很多新手刚接触服务器时,都会被“选购...
星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

  星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...
星哥带你玩飞牛NAS-1:安装飞牛NAS

星哥带你玩飞牛NAS-1:安装飞牛NAS

星哥带你玩飞牛 NAS-1:安装飞牛 NAS 前言 在家庭和小型工作室场景中,NAS(Network Atta...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
150元打造低成本NAS小钢炮,捡一块3865U工控板

150元打造低成本NAS小钢炮,捡一块3865U工控板

150 元打造低成本 NAS 小钢炮,捡一块 3865U 工控板 一块二手的熊猫 B3 工控板 3865U,搭...
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛 NAS-12:开源笔记的进化之路,效率玩家的新选择 前言 如何高效管理知识与笔记,已经成为技术...
小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比 星哥玩云,带你从小白到上云高手。今天咱们就来聊聊——什...
支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare也瘫了连监控都挂,根因藏在哪?

支付宝、淘宝、闲鱼又双叕崩了,Cloudflare 也瘫了连监控都挂,根因藏在哪? 最近两天的互联网堪称“故障...
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...