Java 8 Stream API 中的 peek() 方法详解,以及需要注意的坑。

这篇具有很好参考价值的文章主要介绍了Java 8 Stream API 中的 peek() 方法详解,以及需要注意的坑。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

震惊 java一个大坑, 被老板约谈了。

引言

在Java 8中,Stream API引入了许多强大的函数式编程特性,极大地增强了我们对集合数据进行操作的能力。其中一个很有用的方法就是peek(),本文将详细介绍其功能及应用场景。

peek() 方法简介

peek() 是Java 8 Stream API中的一个中间操作方法,它的主要功能是对流中的每个元素执行一个操作(可以是获取、修改或打印等),而不影响流的整体处理流程。这意味着即使使用了peek(),流也可以继续进行后续的映射、过滤或其他操作。

<T> Stream<T> peek(Consumer<? super T> action);

参数action是一个Consumer接口的实现,它接受一个泛型参数T,并对其执行某种操作。

示例一:简单使用 peek() 打印元素()

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class PeekExample {
    public static void main(String[] args) {
        List<String> addrList = Arrays.asList("AAA");

        addrList.stream()
                .filter(Objects::nonNull)
                .peek(info -> {
                    System.out.println("Processing Element: " + info);
                }).collect(Collectors.toList());

        // 输出:Processing Element: AAA
    }
}

在这个例子中,我们首先创建了一个包含一个元素"AAA"的列表,并将其转换为流。随后使用filter()方法去除可能存在的空元素(在此例中其实无需过滤,因为已知元素不为空)。关键在于peek()方法的应用,它接收一个lambda表达式,每当流中的元素被访问时,就执行该表达式,从而实现了打印当前处理元素的功能。

有坑的点:删除流终止操作,将会不执行。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class PeekExample {
    public static void main(String[] args) {
        List<String> addrList = Arrays.asList("AAA");

        addrList.stream()
                .filter(Objects::nonNull)
                .peek(info -> {
                    System.out.println("Processing Element: " + info);
                });
        // 输出:
    }
}

这段代码中peek不会被执行,并且不会打印

peek()方法是 Strean 接口中的一个中间操作,它允许你在流的每 个元素上执行一个操作,但是这个操作是在最终的终端操作(如
forEach,collect,limit 等)执行 前进行的。 然而,如果 peek()是流中唯一的操作,那么它实际上不会执行。这是因为
peek ()本身并不是一个 终端操作,它不会触发流的执行。在 jav 8 及以后的版本中,流的执行是情性的,这意味着流操作
不会立即执行,而是在遇到终端操作时才会实际执行

示例二:结合 peek() 进行调试

peek()方法的一个常见用途是在调试时查看流中的元素状态,而不会影响到流的最终处理结果。

Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);
numbers.map(n -> n * 2) // 将每个数乘以2
       .peek(n -> System.out.println("Mapped value: " + n))
       .filter(n -> n % 3 == 0) // 过滤出能被3整除的数
       .peek(n -> System.out.println("Filtered value: " + n))
       .collect(Collectors.toList()); // 收集到List中

在上述代码中,我们在映射和过滤操作之间插入了两次peek(),分别用来查看映射后的值和过滤后的值,这对于理解流的处理过程非常有帮助。

总结起来,peek()方法就像是一个观察者,可以在不影响流整体处理的情况下,让我们有机会在每个元素上执行一些额外的操作,例如日志记录、临时计算、调试信息打印等。但它并不改变流的原始内容,也不决定流的最终输出结果。要得到流的处理结果,还需要进一步调用诸如collect(), forEach(), reduce()等终端操作方法。

需要注意的坑

坑一:peek() 不影响流的生成和消费

peek()是一个中间操作,它并不会终止流的处理流程,因此如果不跟一个终端操作(如collect(), forEach(), count()等),则peek()中的操作虽然会被执行,但整个流式处理链的结果不会有任何产出。换言之,只有当流被消耗时,peek()里的操作才会真正发生。

坑二:peek() 的执行次数取决于下游操作

peek()方法中的动作会在流的每个元素上执行一次,但具体执行多少次取决于下游的终端操作。例如,如果你在排序(sorted())前使用了peek(),而在排序后又使用了一次peek(),则同一个元素可能会被两次peek()。

坑三:并发流中的peek()行为

对于并行流,peek()操作的执行顺序没有保证,而且可能会多次执行(取决于JVM的具体调度)。如果你在并行流中依赖peek()的顺序性或唯一性,可能会遇到意想不到的问题。

坑四:资源管理

如果在peek()中打开了一些资源(如文件、数据库连接等),但在peek()内部并未妥善关闭它们,可能会导致资源泄露。因为在没有终端操作的情况下,流可能不会立即执行,资源也就无法及时释放。

坑五:对流元素的修改可能无效

peek()通常用于读取或打印流元素,而不是修改它们。虽然理论上可以尝试在peek()中修改元素,但由于流的惰性求值和可能的不可变性,这样的修改可能不会反映到源集合或后续流操作中。文章来源地址https://www.toymoban.com/news/detail-853112.html

到了这里,关于Java 8 Stream API 中的 peek() 方法详解,以及需要注意的坑。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 空文件夹删不掉打不开,“该项目不存在请确认该项目位置“,“项目正在打开中无法删除“,“文件已损坏或者已经被移动删除“(多种方法图文详解,细节需要注意,以及可能遇到的问题)

    这个删不掉的文件或文件夹其实是Windows系统的祖传bug到目前为止依然没有修复,所以说我们需要通过特别的手段来处理它,听我慢慢讲他的缘由可能会对解决这个问题的帮助更多,会有几种方法,我都试过了的,我把最后一种成功的放在第一个讲,没有成功的可以参考。 事情缘由因

    2024年02月06日
    浏览(89)
  • Java Stream中的API你都用过了吗?

    公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。 在本教程中,您将通过大量示例来学习 Java 8 Stream API。 Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream 。该包由类、接口和枚举组成,允许对元素进行函数式操作。 您可以通过在

    2024年02月05日
    浏览(68)
  • Java Stream API的基本使用方法

    Java各个版本所更新的主要内容: 1.Java SE 8:引入了一些新特性,如lambda表达式、Stream API、格式化日期、国际化等。此外,还对并发编程进行了改进,引入了线程安全的 Stream API 。 2.Java SE 9:新增了分布式架构的支持,引入了CompletableFuture、ZK等新特性。此外,还对Jit编译器进

    2024年02月03日
    浏览(48)
  • Java 8及以上新特性:Lambda表达式、Stream API、Optional类与接口默认方法(四)

    目录 一、接口默认方法 1.1 概念解析: 1.2 应用场景: 1.3 使用注意事项: 1.4 使用示例: 二、结论 1.1 总结Java 8及以上版本四大新特性的重要意义与价值: 1.2 鼓励读者积极学习并运用这些新特性: 1.3 对未来Java版本可能引入的新特性进行展望: 1.1 概念解析: 接口默认方法

    2024年04月13日
    浏览(43)
  • 使用Java8 Stream流中的Collectors.collectingAndThen()方法去重

    Collectors.collectingAndThen() 根据对象属性进行去重操作 Collectors.collectingAndThen()方法属于java8 Stream流中的 java.util.stream.Collectors ,此类实现了 java.util.stream.Collector 接口,还提供了大量的方法对Stream流中的元素进行 map 和 reduce 操作 在获取任务的时候,会出现id重复的状况,利用 Co

    2024年02月09日
    浏览(63)
  • api接口怎么对接?你只需要注意这4点

    原则上API接口设计一般出现在开发的详细设计中,但是随着诸多公司建立开放平台,产品经理也逐渐需要能理解API接口,尤其是做平台性的产品,还要学会定义接口。本文就关于产品经理在设计接口中需要定义什么、需要注意什么来展开陈述。 一、了解API的常识 在做接口设

    2024年02月04日
    浏览(51)
  • Python 中的 multiprocessing 模块和 threading 模块有什么区别?什么情况下应该使用哪一个?解释 Python 中的 __del__ 方法的作用。有什么需要注意的地方解释

    multiprocessing 模块和 threading 模块都是用于在 Python 中进行并发编程的工具,但它们有一些关键的区别。以下是它们之间的比较: 区别: 并行性 vs 并发性: multiprocessing 模块用于创建独立的进程,每个进程都有自己的 Python 解释器和全局解释器锁(GIL)。因此,multiprocessing 允许

    2024年02月22日
    浏览(45)
  • Java对文件的写入和读取 (File类详解以及Input,OutputStream用法,注意事项)

    Java中,操作文件的类有很多, 核心的部分是File类,InputStream,OutputStream类 我们先来看看 File 类中的常见属性、构造方法和方法 属性 修饰符及类型 属性 说明 static String pathSeparator 依赖于系统的路径分隔符,String 类型的表示 static char pathSeparator 依赖于系统的路径分隔符,char 类型的

    2024年02月09日
    浏览(40)
  • 前端开发中需要注意的CSS命名规则以及书写顺序

    1、CSS的命名——BEM规则: CSS命名一般是用 BEM 规则命名的。它背后的想法是将用户界面划分为独立的块。 BEM 的意思就是 B模块(block) 、 E元素(element) 、 M修饰符(modifier) , 即: [block]__[element]--[modifier] 。 模块和子元素之间用两个下划线分隔(如:order__security),子元素和修饰

    2024年02月01日
    浏览(40)
  • 【笔记】Arrays.binarySearch()实践,以及需要注意的一些问题点

    背景:我想校验一个指定的String字符串,是否存在于另一个String数组中,选择 Arrays.binarySearch() 方法实现,代码如下: 运行结果: 很直观的能看到item数组里面存在字符串 1591 ,为什么程序运行的结果却是找不到该元素呢? 首先来看一下源码: 注意,注释上提到了两个重点:

    2024年02月06日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包