Stream流式编程

如何创建 Stream 对象

从集合创建:我们可以通过调用集合的 stream() 方法来创建一个 Stream 对象。例如:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream();

从数组创建:Java 8 引入了 Arrays 类的 stream() 方法,我们可以使用它来创建一个 Stream 对象。例如:

String[] names = {"Alice", "Bob", "Carol"};
Stream<String> stream = Arrays.stream(names);

通过 Stream.of() 创建:我们可以使用 Stream.of() 方法直接将一组元素转换为 Stream 对象。例如:

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

通过 Stream.builder() 创建:如果我们不确定要添加多少个元素到 Stream 中,可以使用 Stream.builder() 创建一个 Stream.Builder 对象,并使用其 add() 方法来逐个添加元素,最后调用 build() 方法生成 Stream 对象。例如:

Stream.Builder<String> builder = Stream.builder();
builder.add("Apple");
builder.add("Banana");
builder.add("Cherry");
Stream<String> stream = builder.build();

从 I/O 资源创建:Java 8 引入了一些新的 I/O 类(如 BufferedReaderFiles 等),它们提供了很多方法来读取文件、网络流等数据。这些方法通常返回一个 Stream 对象,可以直接使用。例如:

Path path = Paths.get("data.txt");
try (Stream<String> stream = Files.lines(path)) {
    // 使用 stream 处理数据
} catch (IOException e) {
    e.printStackTrace();
}

通过生成器创建:除了从现有的数据源创建 Stream,我们还可以使用生成器来生成元素。Java 8 中提供了 Stream.generate() 方法和 Stream.iterate() 方法来创建无限 Stream。例如:

Stream<Integer> stream = Stream.generate(() -> 0); // 创建一个无限流,每个元素都是 0
Stream<Integer> stream = Stream.iterate(0, n -> n + 1); // 创建一个无限流,从 0 开始递增

需要注意的是,Stream 对象是一种一次性使用的对象,它只能被消费一次。一旦对 Stream 执行了终止操作(如收集结果、遍历元素),Stream 就会被关闭,后续无法再使用。因此,在使用 Stream 时,需要根据需要重新创建新的 Stream 对象。

常用的 Stream 操作方法

过滤(Filter):filter() 方法接受一个 Predicate 函数作为参数,用于过滤 Stream 中的元素。只有满足 Predicate 条件的元素会被保留下来。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> filteredStream = stream.filter(n -> n % 2 == 0); // 过滤出偶数

映射(Map):map() 方法接受一个 Function 函数作为参数,用于对 Stream 中的元素进行映射转换。对每个元素应用函数后的结果会构成一个新的 Stream。例如:

Stream<String> stream = Stream.of("apple", "banana", "cherry");
Stream<Integer> mappedStream = stream.map(s -> s.length()); // 映射为单词长度

扁平映射(FlatMap):flatMap() 方法类似于 map() 方法,不同之处在于它可以将每个元素映射为一个流,并将所有流连接成一个流。这主要用于解决嵌套集合的情况。例如:

List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);
Stream<Integer> flattenedStream = nestedList.stream().flatMap(List::stream); // 扁平化为一个流

截断(Limit):limit() 方法可以限制 Stream 的大小,只保留前 n 个元素。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> limitedStream = stream.limit(3); // 只保留前 3 个元素

跳过(Skip):skip() 方法可以跳过 Stream 中的前 n 个元素,返回剩下的元素组成的新 Stream。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> skippedStream = stream.skip(2); // 跳过前 2 个元素

排序(Sorted):sorted() 方法用于对 Stream 中的元素进行排序,默认是自然顺序排序。还可以提供自定义的 Comparator 参数来指定排序规则。例如:

Stream<Integer> stream = Stream.of(5, 2, 4, 1, 3);
Stream<Integer> sortedStream = stream.sorted(); // 自然顺序排序

去重(Distinct):distinct() 方法用于去除 Stream 中的重复元素,根据元素的 equals() 和 hashCode() 方法来判断是否重复。例如:

Stream<Integer> stream = Stream.of(1, 2, 2, 3, 3, 3);
Stream<Integer> distinctStream = stream.distinct(); // 去重

汇总(Collect):collect() 方法用于将 Stream 中的元素收集到结果容器中,如 List、Set、Map 等。可以使用预定义的 Collectors 类提供的工厂方法来创建收集器,也可以自定义收集器。例如:

Stream<String> stream = Stream.of("apple", "banana", "cherry");
List<String> collectedList = stream.collect(Collectors.toList()); // 收集为 List

归约(Reduce):reduce() 方法用于将 Stream 中的元素依次进行二元操作,得到一个最终的结果。它接受一个初始值和一个 BinaryOperator 函数作为参数。例如:

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Optional<Integer> sum = stream.reduce((a, b) -> a + b); // 对所有元素求和

统计(Summary Statistics):summaryStatistics() 方法可以从 Stream 中获取一些常用的统计信息,如元素个数、最小值、最大值、总和和平均值。例如:

IntStream stream = IntStream.of(1, 2, 3, 4, 5);
IntSummaryStatistics stats = stream.summaryStatistics();
System.out.println("Count: " + stats.getCount());
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
System.out.println("Sum: " + stats.getSum());
System.out.println("Average: " + stats.getAverage());

以上只是 Stream API 提供的一部分常用操作方法,还有许多其他操作方法,如匹配(Match)、查找(Find)、遍历(ForEach)等

文章来源:https://www.cnaaa.net,转载请注明出处:https://www.cnaaa.net/archives/9621

(0)
杰斯的头像杰斯
上一篇 2023年8月31日 下午8:27
下一篇 2023年9月5日 下午5:03

相关推荐

  • Proxmox VE 网络配置 NAT共享IP 端口映射iptables、brook

    配置桥接网卡,使Proxmox VE(PVE)可以同时创建NAT虚拟机和独立IP虚拟机,同时可以使用脚本映射NAT虚拟机的端口到外网。 1、开启ipv4、ipv6转发 文件最后加入如下配置 2、 配置Proxmox VE网卡文件信息 新增一个vmbr172网桥,并设置流量转发 重启 3、 搭建DHCP服务器 4、 内外网端口映射转发 Pv4是经过内网转发的,…

    2023年8月2日
    1.5K00
  • 使用Dockerfile创建镜像,创建容器并运行

    一般情况下并不推荐使用“docker commit”来构建镜像,而应该使用更灵活、更强大的Dockerfile来构建Docker镜像,这里就来说一下使用Dockerfile创建镜像,创建容器并运行的方法。 1 生成镜像1.1 准备Dockerfile文件准备Dockerfile文件内容如下: 由于创建过程用到了java文件,这里要将注意这里要将java文件和…

    2023年8月10日
    24400
  • 将 COS 作为本地磁盘挂载到 Windows 服务器

    下载与安装 本案例实践使用到以下三种软件,您可选择安装适用于自己所使用系统的软件版本: 说明: Github 下载速度可能比较慢甚至打不开,可自行在其他官方渠道进行下载。 配置 Rclone 注意: 以下配置步骤以 rclone-v1.60.1-windows-amd64 版本为例,其他版本的配置过程可能存在一定差异,请注意相应调整。 修改配置文件 以上步骤…

    2023年3月8日
    41700
  • Traceroute(路由追踪)的原理及实现

    现实世界中的网络是由无数的计算机和路由器组成的一张的大网,应用的数据包在发送到服务器之前都要经过层层的路由转发。而Traceroute是一种常规的网络分析工具,用来定位到目标主机之间的所有路由器 原理 在介绍Traceroute的原理之前,需要了解几个技术名词: 具体到traceroute的实现细节上,有两种不同的方案: 基于UDP实现 在基于UDP的实现中…

    2023年4月12日
    25400
  • iStoreOS,新增备份系统教程

    一、写盘。 本文主要是x86物理机安装教程(因为物理机才能获取到温度等硬件信息),esxi下安装也很简单,跟安装任何openwrt一样,先转成vmdk文件,添加现有硬盘即可。 我们继续物理机安装教程,首先,用balenaEtcher工具将gz安装包写入U盘,必须要这么做。 所以,请务必写入普通的U盘。 二、接入主机。 将U盘插入小主机,同时将内置硬盘也接入小…

    2023年4月4日
    1.6K00

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

在线咨询: QQ交谈

邮件:712342017@qq.com

工作时间:周一至周五,8:30-17:30,节假日休息

关注微信