Java官方笔记9Lambda表达式

news2024/9/20 1:14:53

Lambda Expression

有了Lambda Expression,就不用再写anonymous classes。

写Lambda,首先要找到它的类型。

There is a restriction on the type of a lambda expression: it has to be a functional interface.

函数接口,只有1个抽象方法的接口:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

默认方法do not count,所以下面这个也是函数接口:

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        // the body of this method has been removed
    }
}

静态方法也do not count,所以下面这个还是函数接口:

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        // the body of this method has been removed
    }

    default Predicate<T> negate() {
        // the body of this method has been removed
    }

    default Predicate<T> or(Predicate<? super T> other) {
        // the body of this method has been removed
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        // the body of this method has been removed
    }

    static <T> Predicate<T> not(Predicate<? super T> target) {
        // the body of this method has been removed
    }
}

接着,实现函数接口的抽象方法,比如Predicate的抽象方法:

boolean test(T t);

实现Predicate<String>

Predicate<String> predicate =
    (String s) -> {
        return s.length() == 3;
    };

省略了返回类型和方法名,只保留参数列表和方法体,用->连接。

再简化:

Predicate<String> predicate = s -> s.length() == 3;

这就是最常见的Lambda,因为前面有String,编译器能够知道,所以这里把(String s)简写为s,然后只有一行,再把大括号和return省略掉。

无return,跟省略掉return:

Consumer<String> print = s -> System.out.println(s);

无参数,用()代替:

Runnable runnable = () -> System.out.println("I am running");

Lambda的使用:

List<String> retainStringsOfLength3(List<String> strings) {

    Predicate<String> predicate = s -> s.length() == 3;
    List<String> stringsOfLength3 = new ArrayList<>();
    for (String s: strings) {
        if (predicate.test(s)) {
            stringsOfLength3.add(s);
        }
    }
    return stringsOfLength3;
}

因为Lambda实现了接口的抽象方法,所以predicate.test(s)调用的实际上是Lambda。

Lambda不能修改变量值:

int calculateTotalPrice(List<Product> products) {

    int totalPrice = 0;
    Consumer<Product> consumer =
        product -> totalPrice += product.getPrice();  // 编译错误
    for (Product product: products) {
        consumer.accept(product);
    }
}

编译错误:Variable used in lambda expression should be final or effectively final

This process of accessing variable is called capturing: lambdas cannot capture variables, they can only capture values. A final variable is in fact a value.

也就是Lambda只能读,不能写。

使用Lambda

Lambda是JDK8跨时代的语法技术,它引领了大量的JDK API重写。

java.util.function中包含了很多可供实现的函数接口,functional interfaces:

https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/function/package-summary.html

比如:

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

Lambda实现:

Supplier<String> supplier = () -> "Hello Duke!";`

使用:

Random random = new Random(314L);
Supplier<Integer> newRandom = () -> random.nextInt(10);

for (int index = 0; index < 5; index++) {
    System.out.println(newRandom.get() + " ");
}

比如:

List<String> strings = ...; // really any list of any kind of objects
Consumer<String> printer = s -> System.out.println(s);
strings.forEach(printer);

比如:

List<String> immutableStrings =
        List.of("one", "two", "three", "four", "five");
List<String> strings = new ArrayList<>(immutableStrings);
Predicate<String> isOddLength = s -> s.length() % 2 == 0;
strings.removeIf(isOddLength);
System.out.println("strings = " + strings);

比如:

@FunctionalInterface
public interface Function<T, R> {

    R apply(U u);

    // default and static methods removed
}
Function<String, Integer> toLength = s -> s.length();
String word = ...; // any kind of word will do
int length = toLength.apply(word);

以上是JDK中最经典的4种function interface

  • Supplier<T>
  • Consumer<T>
  • Predicate<T>
  • Function<T, R>

总结一下,Lambda的使用就是先实现function interface的abstract method,然后①接口实例调用abstract method,或者②接口实例被forEach等调用。

Lambda使得function interface能够实例化:Predicate<String> isOddLength = s -> s.length() % 2 == 0;

The java.util.function package is now central in Java, because all the lambda expressions you are going to use in the Collections Framework or the Stream API implement one of the interfaces from that package.

发现没有,把:

List<String> strings = ...; // really any list of any kind of objects
Consumer<String> printer = s -> System.out.println(s);
strings.forEach(printer);

简写一下,去掉中间的接口实例:

List<String> strings = ...; // really any list of any kind of objects
strings.forEach(s -> System.out.println(s));

这不就是常见到的Lambda的形态嘛。换句话说,Lambda的结果就是函数接口实例(Function interface instance),使用Lambda本质上就是调用函数,Java中没有函数的概念,通过function interface的abstract method,引入了函数,从而造就了Lambda。

Method References

Sometimes people call these lambda expressions "anonymous methods", since it is just that: a method that has no name, and that you can move around your application, store in a field or a variable, pass as an argument to a method or a constructor and return from a method.

Consumer<String> printer = s -> System.out.println(s);

这里的Lambda没有什么逻辑,其实就是System.out.println()方法的引用,所以可以简写为Bound(System.out优化前后一致):

Consumer<String> printer = System.out::println;

Static:

IntBinaryOperator max = (a, b) -> Integer.max(a, b);
IntBinaryOperator max = Integer::max;

Unbound(优化前s,优化后String;优化前user,优化后User):

Function<String, Integer> toLength = s -> s.length();
Function<String, Integer> toLength = String::length;
Function<User, String> getName = user -> user.getName();
Function<String, Integer> toLength = User::getName;
BiFunction<String, String, Integer> indexOf = (sentence, word) -> sentence.indexOf(word);
BiFunction<String, String, Integer> indexOf = String::indexOf;

Constructor:

Supplier<List<String>> newListOfStrings = () -> new ArrayList<>();
Supplier<List<String>> newListOfStrings = ArrayList::new;

总结:

Combining Lambda Expressions

Function interface中的defualt method该登场了。

Predicate<String> nonNull = s -> s != null;
Predicate<String> nonEmpty = s -> s.isEmpty();
Predicate<String> shorterThan5 = s -> s.length() < 5;

Predicate<String> p = nonNull.and(nonEmpty).and(shorterThan5);

这里的and()就是default method,它实现了Lambda的组合,也就是链式调用的既视感。

稍复杂点的:

Predicate<String> isNull = Objects::isNull;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNullOrEmpty = isNull.or(isEmpty);
Predicate<String> isNotNullNorEmpty = isNullOrEmpty.negate();
Predicate<String> shorterThan5 = s -> s.length() < 5;

Predicate<String> p = isNotNullNorEmpty.and(shorterThan5);

Comparators

@FunctionalInterface
public interface Comparator<T> {

    int compare(T o1, T o2);
}

Lambda实现:

Comparator<Integer> comparator = (i1, i2) -> Integer.compare(i1, i2);
Comparator<Integer> comparator = Integer::compare;

Comparator的静态方法:

Comparator<String> comparator = Comparator.comparing(String::length);

This comparing() method is a static method of the Comparator interface. It takes a Function as an argument, that should return a type that is an extension of Comparable.

使用:

List<User> users = ...; // this is your list
Comparator<User> byName = Comparator.comparing(User::getName);
users.sort(byName);

还有默认方法thenComparing:

Comparator<User> byFirstNameThenLastName =
        Comparator.comparing(User::getFirstName)
                  .thenComparing(User::getLastName);

参考资料:

Lambda Expressions https://dev.java/learn/lambdas/

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

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

相关文章

Vue中v-text、v-html、v-on的基本语法(二)

文章目录 前言一、vue中data属性定义对象、数组相关数据二、v-text、v-html指令使用三、v-on基本指令使用(一)四、v-on指令基本使用(二)之在函数中获取vue实例本身this五、v-on指令基本使用(二)之在函数中传递参数六、v-on指令基本使用(二)之简化写法绑定函数和事件定义的两种写…

从零搭建一台基于ROS的自动驾驶车-----2.运动控制

系列文章目录 北科天绘 16线3维激光雷达开发教程 基于Rplidar二维雷达使用Hector_SLAM算法在ROS中建图 Nvidia Jetson Nano学习笔记–串口通信 Nvidia Jetson Nano学习笔记–使用C语言实现GPIO 输入输出 Autolabor ROS机器人教程 从零搭建一台基于ROS的自动驾驶车-----1.整体介…

Unreal 5 实现丧尸伤害和死亡

这一篇主要是实现玩家攻击丧尸可以造成伤害和自身血量为零时&#xff0c;丧尸可以死亡。丧尸也可以对玩家造成伤害&#xff0c;有攻击范围的判定。 这一篇的功能实现有四个功能&#xff1a; 丧尸被攻击掉血丧尸死亡处理玩家被攻击掉血玩家死亡处理 丧尸被攻击掉血 子弹的修改…

C语言内存操作函数,memcpy的使用和模拟实现,memmove的使用和模拟实现,memcmp的使用,memset的使用。

1.memcpy 函数原型&#xff1a; void *memcpy( void *dest, const void *src, size_t count );void *dest 目标数据首元素地址const void *src 源数据(需要拷贝过去的数据)size_t count 需要拷贝数据的字节大小void *memcpy 拷贝结束后&#xff0c;返回目标数据的起始地址 函…

【简单的图像信息展示应用程序】PYQt5

写在前面的话 这段代码的作用是创建一个简单的图像信息展示应用程序&#xff0c;用户可以点击按钮查看特定文件夹中图像的文件名、大小&#xff0c;并通过查看按钮查看图像。请注意&#xff0c;文件夹路径需要根据实际情况进行修改。 代码讲解 这段代码是使用PyQt5库创建一个…

特征选择:过滤法,嵌入法,包装法

特征选择时首先要去除冗余特征。 它是由其他其他的特征中推演出来的。比如&#xff0c;一个球的体积&#xff0c;那么半径这个特征就是冗余的&#xff0c;因为我们可以由球的体积推算半径。冗余特征在很多时候都是不起作用的 过滤法 过滤方法通常用作预处理步骤&#xff0c;特…

c++11 标准模板(STL)(std::basic_ios)(三)

定义于头文件 <ios> template< class CharT, class Traits std::char_traits<CharT> > class basic_ios : public std::ios_base 类 std::basic_ios 提供设施&#xff0c;以对拥有 std::basic_streambuf 接口的对象赋予接口。数个 std::basic_ios…

2013年全国硕士研究生入学统一考试管理类专业学位联考英语(二)试题

2013考研英语&#xff08;二&#xff09;真题 Section I Use of English Directions: Read the following text. Choose the best word(s) for each numbered blank and mark A, B, C or D on ANSWER SHEET 1. (10 points) Given the advantages of electronic money, you mi…

某农业大学数据结构A-第2周作业

1.两个顺序表集合的差集 【问题描述】两个顺序表集合的差集 【样例输入】 25 33 57 60 48 9 13 0 12 50 23 60 4 34 25 13 0 【样例输出】 33 57 48 9 【注意】0代表输入的结束&#xff1b;可以用C风格实现&#xff0c;也可以用C风格实现&#xff0c;两种风格大家均需掌握 #…

Kafka架构

5.kafka系统的架构 5.1主题topic和分区partition topic Kafka中存储数据的逻辑分类&#xff1b;你可以理解为数据库中“表”的概念&#xff1b; 比如&#xff0c;将app端日志、微信小程序端日志、业务库订单表数据分别放入不同的topic partition分区&#xff08;提升kafka吞…

【Proteus仿真】常用器件名称

前言 我常用的仿真器件加上收集的&#xff0c;基于Proteus8.13版本。以下分为两部分&#xff0c;内容都一样&#xff0c;一部分是纯文字&#xff0c;一部分是文字图片&#xff0c;方便快速获取和定位。等积累了更多的器件后会在更新的。搜索时可以用CtrlF快速查找。 命名的规则…

管理类联考——英语二——技巧篇——写作——B节——议论文——必备替换句型

议论文必备替换句型 (一&#xff09;表示很明显/众所周知的句型 It is obvious thatIt is clear thatIt is apparent thatIt is evident thatlt is self-evident thatIt is manifest thatIt is well-knownIt is known to all thatIt is widely-accepted thatIt is crystal-cl…

三层交换机互联互通配置 华为交换机

#三层交换机互联互通 交换机配置 命令 #进入系统视图 <Huawei>system-view #关闭系统提示信息 [Huawei]undo info-center enable #创建三个Vlan10 [Huawei]vlan 10 [Huawei-vlan10]quit [Huawei]vlan 20 [Huawei-vlan20]quit [Huawei]vlan 30 [Huawei-vlan30]quit #接…

2023六月第二周(juc知识点记录)

1、多线程资源竞争 先创建资源类&#xff0c;并给线程加锁&#xff0c;推荐使用reatrantlock&#xff0c;然后写业务&#xff0c; 加锁了说明肯定要有执行条件&#xff0c;例如抢到锁还要判断库存必须大于0&#xff0c; 否则线程等待await,然后执行业务&#xff0c;最后创建多个…

一分钟图情论文:《运用服务场景模型理解挪威学术图书馆中的学生体验》

一分钟图情论文&#xff1a;《Applying the servicescape model to understand student experiences of a Norwegian academic library》 1981年&#xff0c;Booms, B. H.和Bitner, M. J.1在一篇市场营销学科的论文中引入了Servicescape模型&#xff0c;用于描述和分析服务场所…

无线供电原理、种类及应用方案介绍

目录 一、无线供电种类 二、无线供电的原理 磁共振技术的电路组成 微波能量传输 三、无线供电的优势 四、市场应用 五、市场趋势 参考文献 一、无线供电种类 包含电磁场耦合能量传输&#xff08;电磁磁感应&#xff08;近场供电&#xff09;、磁共振&#xff08;远场供…

easyX库颜色模型和颜色及样式设置相关函数(注释版)

0.颜色模型和颜色及样式设置相关函数概览 本次我给你带了easyX库系列的颜色模型和样式设置的相关函数&#xff0c;希望您能看得开心。 函数或数据类型描述LINESTYLE画线样式对象。FILLSTYLE填充样式对象。setbkcolor设置当前设备绘图背景色。setlinecolor设置当前设备画线颜色…

[易语言][原创]使用易语言部署yolov8的onnx模型

易语言部署yolo系列模型&#xff0c;现在网上有很多但是他们不够简洁也不够专业&#xff0c;有人专门把opencv封装成易语言支持库然后用opencv在易语言端写&#xff0c;其实这种效率没有在C直接推理效率高&#xff0c;因为易语言往C传递图像数据集是需要转换图像数据集格式才能…

十一、docker学习-docker核心之docker网络(1)

docker网络 当开始大规模使用docker时&#xff0c;你会发现需要了解很多关于网络的知识。docker作为目前最火的轻量级容器技术&#xff0c;有很多令人称道的功能&#xff0c;如docker的镜像管理。然而&#xff0c;docker同样有着很多不完善的地方&#xff0c;网络方面就是Dock…

Nexus搭建Maven私有库介绍

为什么需要Maven私有库&#xff1f; 使用Maven获取Java依赖包的时候&#xff0c; 默认是从Maven的中央库下载 jar文件&#xff0c; 中央库的地址是&#xff1a; https://repo.maven.apache.org/maven2 。 如果下载速度慢&#xff0c; 可以使用阿里的镜像&#xff0c; 地址如下…