大厂必备Stream流、方法引用的使用

news2024/9/27 7:26:44

大厂必备Stream流、方法引用的使用

1 Stream的基本使用

1.1 思想

当需要对多个元素进行操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该首先拼好一个“模型”步骤方案,然后再按照方案去执行它。【流水线】

在这里插入图片描述

这张图中展示了过滤、映射、跳过、计数等多步操作,这是一种集合元素的处理方案,而方案就是一种“函数模型”。图中的每一个方框都是一个“流”,调用指定的方法,可以从一个流模型转换为另一个流模型。而最右侧的数字3是最终结果。

注意:“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

1.2 获取流的方式

java.util.stream.Stream是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)

①根据Collection

java.util.Collection接口中加入了default方法stream用来获取流,所以其所有实现类均可获取流。

@Test
public void test(){
    List<String> list = new ArrayList<>();
    // ...
    Stream<String> stream1 = list.stream();

    Set<String> set = new HashSet<>();
    // ...
    Stream<String> stream2 = set.stream();
}

②根据数组获取(Stream.of)

如果使用的不是集合或映射而是数组,由于数组对象不可能添加默认方法,所以Stream接口中提供了静态方法of
of方法的参数其实是一个可变参数,所以支持数组。

@Test
public void test(){
    Integer[] arr = {1,2,3};
    Stream<Integer> stream = Stream.of(arr);
    //Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5)
}

1.3 Stream流的常用方法

流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:

  • 终结方法:返回值类型不再是Stream接口自身类型的方法,因此不再支持类似StringBuilder那样的链式调用。本小节中,终结方法包括count和forEach方法。【返回值不是stream,不支持继续链式调用】
  • 非终结方法:返回值类型仍然是Stream接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为非终结方法。)

①forEach

虽然方法名字叫forEach,但是与for循环中的“for-each”昵称不同,该方法并不保证元素的逐一消费动作在流中是被有序执行的。【非终结方法】

@Test
public void test(){
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    stream.forEach(i -> System.out.println(i));
}

在这里,lambda表达式(Integer i)->{System.out.println(i);}就是一个Consumer函数式接口的示例。

②filter

可以通过filter方法将一个流转换成另一个子集流【非终结】

@Test
public void test(){
    Stream<Integer> original = Stream.of(1, 2, 3, 4, 5);
    Stream<Integer> result = original.filter(i -> {
        return i > 3;
    });
    result.forEach(num -> {System.out.println(num);});//4,5
}

③count

统计流中元素的个数,类似于Collection中的size()【终结方法】

 @Test
 public void test(){
     Stream<Integer> original = Stream.of(1, 2, 3, 4, 5);
     Stream<Integer> result = original.filter(i -> {
         return i > 3;
     });
     System.out.println(result.count());//2
 }

④limit

limit方法可以对流进行截取,只取用前n个。【非终结】
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作。

@Test
public void test() {
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    Stream<Integer> result = stream.limit(2);
    //1 2
    result.forEach(i -> {
        System.out.print(i+" ");
    });
}

⑤skip

如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:【非终结】

@Test
public void test() {
    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
    Stream<Integer> result = stream.skip(2);
    //3 4 5 
    result.forEach(i -> {
        System.out.print(i+" ");
    });
}

⑥concat

如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat【非终结】

@Test
public void test() {
    Stream<Integer> stream1 = Stream.of(1, 2, 3);
    Stream<Integer> stream2 = Stream.of(4, 5, 6);
    Stream<Integer> result = Stream.concat(stream1, stream2);
    result.forEach(i -> {
        //1 2 3 4 5 6 
        System.out.print(i + " ");
    });
}

综合运用

@Test
public void test() {
    Stream<Integer> stream1 = Stream.of(1, 2, 3);
    Stream<Integer> stream2 = Stream.of(4, 5, 6);
    //1,2,3,4,5,6 -> 2,3,4,5,6[skip] -> 2,3,4,5[filter] -> 2,3,4[limit]
    Stream.concat(stream1, stream2).skip(1).filter(i -> {
        return i <= 5;
    }).limit(3).forEach(num -> {System.out.print(num + " ");});

}

2 方法引用

双冒号为方法引用运算符,而它所在的表达式被称为方法引用。

2.1 概述

来看一个简单的函数式接口以应用Lambda表达式 , 在accept方法中接收字符串 , 目的就是为了打印显示字符串 , 那么通过Lambda来使用它的代码很简单:

public class DemoPrintSimple {
    private static void printString(Consumer<String> data, String str) {
        data.accept(str);
    }
    public static void main(String[] args) {
      	printString(s -> System.out.println(s), "Hello World");
    }
}

由于lambda表达式中,调用了已经实现的println方法 ,可以使用方法引用替代lambda表达式.
如果Lambda要表达的函数方案 , 已经存在于某个方法的实现中,那么则可以使用方法引用。

如上例中,System.out对象中有个println(String)方法 , 恰好就是我们所需要的 , 那么对于Consumer接口作为参数,对比下面两种写法,完全等效:

  • Lambda表达式写法:s -> System.out.println(s);
    拿到参数之后经Lambda之手,继而传递给System.out.println方法去处理。
  • 方法引用写法:System.out::println
    直接让System.out中的println方法来取代Lambda。
@Test
public void test4(){
    List<Integer> list = new ArrayList<>();
    list.add(2);
    list.add(1);
    list.add(3);
    list.stream().forEach(System.out::println);
}

2.2 引用方式

①引用成员方法(str::toUpperCase)

@Test
public void test4(){
    String str = "fas";
    printUp(str::toUpperCase);
}

public void printUp(Supplier<String> supplier){
    System.out.println(supplier.get());
}

②引用静态方法(Math::random)

@Test
public void test4(){
    getNum(Math::random);
}

public void getNum(Supplier<Double> supplier){
    System.out.println(supplier.get());
}

③类构造引用

Function<String, Cat>中String是source,Cat是target

@Test
public void test4(){
    Cat cat = getCat(Cat::new, "tom");
    System.out.println(cat);
}

public Cat getCat(Function<String, Cat> function, String name){
    Cat cat = function.apply(name);
    return cat;
}

④数组构造引用

@Test
public void test4(){
    int[] arr = getArr(int[]::new, 1);
    System.out.println(arr);
}

public int[] getArr(Function<Integer, int[]> function, Integer num){
    int[] arr = function.apply(num);
    return arr;
}

注意 : 方法引用是对Lambda表达式符合特定情况下的一种缩写,它使得我们的Lambda表达式更加的精简,也可以理解为Lambda表达式的缩写形式
参考文章:
https://juejin.cn/post/6896614244385554446

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/139989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring源码-容器refresh

spring源码 铺垫 1.xml信息封装 我们可以预测的大致顺序 xml里的bean 封装成对象定义信息更容易进一步的 创建 注入 BeanDefinition的属性&#xff1a;可以看出是对xml里信息的封装 public interface BeanDefinitionReader 定义规范2.使用反射 为什么不用new创建对象&#x…

NXP EMDA学习(1):TCD寄存器详解

eDMA(Enhanced DMA)即增强型DMA&#xff0c;它是NXP芯片中独有的功能&#xff0c;其最重要的一个特性也是eDMA的核心就是TCD(Transfer Control Descriptor)即传输控制描述符。所以&#xff0c;我们就来看一下这个结构体中各个字段的内容的含义&#xff0c;对这些字段有一个基础…

位置检测有哪些传感器可以用?(带磁编码器AS5600代码)

常见的有三种 编码器、霍尔传感器、磁传感器。 编码器一般指AB相正交脉冲的增量器件&#xff0c;有的还会有一个Z相信号&#xff0c;用来指示零位&#xff1b; 霍尔传感器一般是指ABC三个成120度角度间隔排列的器件&#xff0c;这种传感器一般集成在电机内部&#xff0c;电机…

[Amazon]人工智能入门学习笔记---AI-机器学习-深度学习

⬜⬜⬜ &#x1f430;&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; (*^▽^*)欢迎光临 &#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;&#x1f430;⬜⬜⬜ ✏️write in front✏️ &#x1f4dd;个人主页&#xff1a;陈丹宇jmu &a…

基于模型预测控制的波浪能转换器(WEC)研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Flink简介

Flink 系列教程传送门 第一章 Flink 简介 第二章 Flink 环境部署 第三章 Flink DataStream API 第四章 Flink 窗口和水位线 第五章 Flink Table API&SQL 第六章 新闻热搜实时分析系统 前言 流计算产品实时性有两个非常重要的实时性设计因素&#xff0c;一个是待计算…

基于 Docker 的 Neo4j 部署及数据备份与恢复

目录一、部署二、验证三、备份3.1 离线备份3.2 在线备份3.3 社区版备份一、部署 1、pull 镜像 docker pull neo4j:4.4.16-community2、创建目录 mkdir -p /home/data/neo4j/{data,logs,conf,import,db-backup}3、运行容器 docker run -itd \--name neo4j \--restart always…

openwrt-看门狗watchdog

一、硬件watchdog和软件watchdog Linux内核不仅为各种不同类型的watchdog硬件电路提供了驱动&#xff0c;还提供了一个基于定时器的纯软件watchdog驱动&#xff0c;软件watchdog基于内核的定时器实现&#xff0c;当内核或中断出现异常时&#xff0c;软件watchdog是无法复位系统…

二叉树17:路径总和

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;112. 路径总和 112. 路径总和 题目&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判…

判断图中有没有证件图片

整体解决思路: 前提:拍摄场景光线稳定,证件没有放在图像边缘;且图片使用的证件阅读器拍摄的红外图片,采用了开灯和关灯各拍摄一张图片,图像相减,进行了背景去除; 1)使用二值化和膨胀腐蚀以及sobel算子等进行图像的预处理; 2)进行凸包计算,通过角度,进行证件区域…

缓存穿透,缓存雪崩,缓存击穿的超详解

文章目录1、缓存穿透问题的解决思路2、缓存雪崩问题及解决思路3、缓存击穿问题及解决思路1、缓存穿透问题的解决思路 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库&#xff0c;失去了缓存的意…

pytorch数据dataset的三种读取方式

文章目录1.自带的datasets2.ImageFolder3.自己创建的dataset&#xff08;用的多&#xff09;1.自带的datasets pytorch自带的数据集 具体数据集如下&#xff1a; 用法&#xff1a; 可以用的功能 2.ImageFolder 文件形式如下时用此&#xff1a;&#xff08;一个文件下只…

MyBatis框架 入门案例

二刷复习简介MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Jav…

磨金石教育科技摄影技能干货分享|艺术摄影的本源是创作,核心是表达

艺术类的作品一直都有一个风格&#xff0c;那就是抽象。特别是摄影领域&#xff0c;一幅作品如果缺乏创意&#xff0c;只是展现现实的景物&#xff0c;那么很容易就变成了纪实摄影或者风光摄影。因此&#xff0c;要想让作品突出艺术性&#xff0c;就要再原有的画面上&#xff0…

Exynos_4412——中断处理(中断学习结尾篇)

目录 一、ARM的异常处理机制 1.1异常概念 1.2异常处理机制 1.3ARM异常源 1.4异常模式 1.5ARM异常响应 1.6异常向量表 1.7异常返回 1.8IRQ异常举例 二、工程模板代码结构 三、中断处理框架搭建 四、中断处理程序 五、用key3再试一试 前景提要&#xff1a; Exynos_…

利用Model Inspector的建模规则检查

利用Model Inspector的规则检查 Model Inspector是一种基于模型的软件静态验证自动化解决方案。通过对模型进行规则检查,开发人员的工作成本将减少,开发效率将会大大提高。 Model Inspector支持各种行业标准建模规范,对违反规范进行检查。 用户可通过dashboard获知模型质量指标…

滴滴前端一面常考手写面试题合集

使用Promise封装AJAX请求 // promise 封装实现&#xff1a; function getJSON(url) {// 创建一个 promise 对象let promise new Promise(function(resolve, reject) {let xhr new XMLHttpRequest();// 新建一个 http 请求xhr.open("GET", url, true);// 设置状态的…

磨金石教育摄影技能干货分享|优秀摄影作品欣赏——艺术的表达

艺术摄影是难以欣赏的&#xff0c;这是大部分人的共识。艺术作品的创作也自然具有较高的难度&#xff0c;很多时候画面的表达与思想不符。要么内容不足以反应思想&#xff0c;要么思想太浅&#xff0c;而内容太杂。想要真正理解作者要表达什么&#xff0c;就要从内容去逐个分解…

ZigBee案例笔记 -- 外部中断

文章目录1.中断概述2.中断屏蔽3.中断处理4.按键中断控制LED1.中断概述 CC2530有18个中断源&#xff0c;每个中断源都有它自己的位于一系列 SFR 寄存器中的中断请求标志。相应标志位请求的每个中断可以分别使能或禁用&#xff0c;中断分别组合为不同的、可以选择的优先级别&…

分布式ID之雪花算法

分布式ID常见生成策略 分布式ID生成策略常见的有如下几种: 数据库自增ID。UUID生成。Redis的原子自增方式。数据库水平拆分&#xff0c;设置初始值和相同的自增步长。批量申请自增ID。雪花算法。百度UidGenerator算法(基于雪花算法实现自定义时间戳)。美团Leaf算法(依赖于数据…