百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Java Lambda详解(java lambda用法)

toyiye 2024-09-19 04:49 4 浏览 0 评论

Lambda表达式是JDK 8开始后的一种新语法形式。

作用:简化匿名内部类的代码写法

简化格式

(匿名内部类被重写方法的形参列表) -> {
	重写方法
}

Lambda表达式只能简化函数式接口的匿名内部类的写法形式

什么是函数式接口?

  • 首先必须是接口、其次接口中有且仅有一个抽象方法的形式
  • 通常会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口

如何使用Lambda?

我们将根据下面三个问题来帮助大家理解和使用Lambda

背景:我们自定义了一个man的类,创建了一个man的List。

class man {
    public int age;
    public char sex;
    public double socre;

    public man(int age, char sex, double score) {
        this.age = age;
        this.sex = sex;
        this.score = score;
    }
}

问题一

现需要对这个list根据人的年龄进行排序

要实现排序的功能,可以直接调用List对象自带的sort方法完成,但是需要man先实现Comparator的接口并重写compare方法,编译器才能比较两个不同man的大小。但是要更改原始类的代码,会比较麻烦,如果以后要对人的分数进行排序,那就又要更改原始类的源码,这样操作很不方便。

sort(Comparator<? super E> c) 方法可以直接传入一个Comparator对象,我们可以直接改写compare方法就可以实现比较。

第一种写法

public class lambdaTry {
    public static void main(String[] args) {
        List<man> humans = new ArrayList<>();
        humans.add(new man(19, 'g', 98.0));
        humans.add(new man(18, 'b', 95.0));
        humans.add(new man(20, 'b', 96.0));
        humans.add(new man(17, 'g', 97.0));

        humans.sort(new Comparator<man>() {
            @Override
            public int compare(man o1, man o2) {
                return o1.age - o2.age;
            }
        });
    }
}

第二种写法

Lambda

我们知道Lambda是用来简化函数式接口的匿名内部类,且Comparator满足函数式接口的两个条件:

  • 首先必须是接口、其次接口中有且仅有一个抽象方法的形式
  • @FunctionalInterface注解
@FunctionalInterface
public interface Comparator<T> {
	int compare(T o1, T o2);
    ...
}

因此我们可以对上述的源码进行改写成Lambda格式

public class lambdaTry {
    public static void main(String[] args) {
        List<man> humans = new ArrayList<>();
        humans.add(new man(19, 'g', 98.0));
        humans.add(new man(18, 'b', 95.0));
        humans.add(new man(20, 'b', 96.0));
        humans.add(new man(17, 'g', 97.0));

        humans.sort((man o1, man o2) -> {
                return o1.age - o2.age;
        });
    }
}

改写过后代码简洁了很多。但是还可以继续简写。

Lambda表达式的省略写法

  1. 参数类型可以不写
  2. 如果只有一个参数,参数类型可以省略,同时()也可以省略
  3. 如果Lambda表达式的方法块中代码只有一行,可以省略大括号,同时省略分号。
  4. 在条件三的基础上,如果这行代码是return语句,必须省略return。

第三种写法

Lambda简写

可以看到,此表达式满足省略写法的条件,可以继续简写成如下格式。只需要一行语句就能完成

public class lambdaTry {
    public static void main(String[] args) {
        List<man> humans = new ArrayList<>();
        humans.add(new man(19, 'g', 98.0));
        humans.add(new man(18, 'b', 95.0));
        humans.add(new man(20, 'b', 96.0));
        humans.add(new man(17, 'g', 97.0));

        humans.sort((o1, o2) -> o1.age - o2.age);
    }
}

问题二

将List转换为数组

我们知道List接口有一个方法toArray方法可以实现将其转换为数组。

JDK11之后,提供了这样的一个方法,提供了一个函数式接口来让我们转换

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

IntFunction函数式接口是从JDK8之后实现的,内部只有一个apply抽象方法,是一个标准的函数式接口

@FunctionalInterface
public interface IntFunction<R> {
    R apply(int value);
}

我们可以直接用lambda,完成数组的转换

public class lambdaTry {
    public static void main(String[] args) {
        List<man> humans = new ArrayList<>();
        humans.add(new man(19, 'g', 98.0));
        humans.add(new man(18, 'b', 95.0));
        humans.add(new man(20, 'b', 96.0));
        humans.add(new man(17, 'g', 97.0));

		// 原本写法
        // man[] mans = humans.toArray(new IntFunction<man[]>() {
        //     @Override
        //     public man[] apply(int value) {
        //         return new man[value];
        //     }
        // });

        // lambda写法
        man[] mans = humans.toArray(value -> new man[value]);
        
        // 实际上用不上这样的写法,只是为了举例说明
        // man[] mans = humans.toArray(new man[0]);
        // man[] mans = humans.toArray(man[]::new);
        // 上面两种写法都可以,传值进去的size为0不影响实际的转换,具体可以看ArrayList的toArray重写方法
        
    }
}

问题三

输出年龄大于18的男同学的成绩

可以用forEach方法快捷实现,forEach方法来自于Iterable接口

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

再看Consumer接口,也是一个函数式接口

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    ...
}

具体实现

public class lambdaTry {
    public static void main(String[] args) {
        List<man> humans = new ArrayList<>();
        humans.add(new man(19, 'g', 98.0));
        humans.add(new man(18, 'b', 95.0));
        humans.add(new man(20, 'b', 96.0));
        humans.add(new man(17, 'g', 97.0));

        // humans.forEach(new Consumer<>() {
        //     @Override
        //     public void accept(man man) {
        //         if (man.age >= 18 && man.sex == 'g') {
        //             System.out.println(man.score);
        //         }
        //     }
        // });

        humans.forEach(man -> {
            if (man.age >= 18 && man.sex == 'g') {
                System.out.println(man.score);
            }
        });
    }
}

有时Lambda还可以继续简写成方法引用(method reference)

方法引用

方法引用通过方法的名字来指向一个方法。

方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

方法引用使用一对冒号 ::

主要分为四种:

  • 构造器引用 Class::new
  • man[] mans = humans.toArray(man[]::new);
  • 静态方法引用 Class::static_method
  • 打印每个man(需要在man内重写toString)
  • humans.forEach(System.out::println)
  • 特定类的任意对象的方法引用 Class::method
  • 特定对象的方法引用 instance::method

如果你觉得这篇文章对你有帮助 点赞关注,然后私信回复【888】即可免费获取Java进阶全套视频以及源码学习资料

相关推荐

Asterisk-ARI对通道中的DTMF事件处理

Asterisk通道中关于DTMF处理是一个非常重要的功能。通过DTMF可以实现很多的业务处理。现在我们介绍一下关于ARI对通道中的DTMF处理,我们通过自动话务员实例来说明Asterisk如何创建一...

PyQt5 初次使用(pyqt5下载官网)

本篇文章默认已安装Python3,本篇文章默认使用虚拟环境。安装pipinstallPyQt5PyQt一些图形界面开发工具QtDesigner、国际化翻译工具Liguist需要另外...

Qt开发,使用Qt for Python还是Qt C++ Qt开发,使用Qt for

Qt开发使用QtforPython还是QtC++?1.早些年写过一个PyQt5的项目,最近几年重构成QtC++了,其中有个人原因,如早期代码写得烂,...

最简单方法!!用python生成动态条形图

最近非常流行动态条形图,在B站等视频网站上,此类视频经常会有上百万的播放量,今天我们通过第三方库:bar_chart_race(0.2版本)来实现动态条形图的生成;生成的效果如图:问题:...

Asterisk通道和ARI接口的通信(aau通道数)

Asterisk通道和ARI详解什么是通道Asterisk中,通道是介于终端和Asterisk自己本身的一个通信媒介。它包含了所有相关信息传递到终端,或者从终端传递到Asterisk服务器端。这些信...

Python GUI-长链转短链(长链接转化成短链接java)

当我们要分享某一个链接给别人,或是要把某个链接放入帖子中时,如果链接太长,则会占用大量空间,而且很不美观。这时候,我们可以结束长链转短链工具进行转换。当然可以直接搜索在线的网站进行转换,但我们可以借此...

Python 的hash 函数(python的hash函数)

今天在看python的hash函数源码的时候,发现针对不同的数据类型python实现了不同的hash函数,今天简单介绍源码中提到的hash函数。(https://github.com/pyth...

8款Python GUI开源框架,谁才是你的菜?

作为Python开发者,你迟早都会用到图形用户界面来开发应用。本文千锋武汉Python培训小编将推荐一些PythonGUI框架,希望对你有所帮助。1、Python的UI开发工具包Kivy...

python适合开发桌面软件吗?(python可不可以开发桌面应用软件)

其实Python/Java/PHP都不适合用来做桌面开发,Java还是有几个比较成熟的产品的,比如大名鼎鼎的Java集成开发环境IntelliJIDEA、Eclipse就是用Java开发的,不过PH...

CryptoChat:一款功能强大的纯Python消息加密安全传输工具

关于CryptoChatCryptoChat是一款功能强大的纯Python消息加密安全传输工具,该工具专为安全研究专家、渗透测试人员和红蓝队专家设计,该工具可以完全保证数据传输中的隐私安全。该工具建立...

为什么都说Python简单,但我觉得难?

Python普遍被大家认为是编程语言中比较简单的一种,但有一位电子信息的学生说自己已经学了C语言,但仍然觉得Python挺难的,感觉有很多疑问,像迭代器、装饰器什么的……所以他提出疑问:Python真...

蓝牙电话-关联FreeSwitch中继SIP账号通过Rest接口

蓝牙电话-关联FreeSwitch中继SIP账号通过Rest接口前言上一篇章《蓝牙电话-与FreeSwitch服务器和UA坐席的通话.docx》中,我们使用开源的B2B-UA当中经典的FreeSWIT...

技术分享|Sip与WebRTC互通-SRProxy开源库讲解

SRProxy介绍目前WebRTC协议跟SIP协议互通场景主要运用在企业呼叫中心、企业内部通信、电话会议(PSTN)、智能门禁等场景,要想让WebRTC与SIP互通,要解决两个层面的...

全网第N篇SIP协议之GB28181注册 JAVA版本

鉴于网上大部分关于SIP注册服务器编写都是C/C++/python,故开此贴,JAVA实现也贴出分享GB28181定义了了基于SIP架构的视频监控互联规范,而对于多数私有协议实现的监控系统...

「linux专栏」top命令用法详解,再也不怕看不懂top了

在linux系统中,我们经常使用到的一个命令就是top,它主要是用来显示系统运行中所有的进程和进程对应资源的使用等信息,所有的用户都可以使用top命令。top命令内容量丰富,可令使用者头疼的是无法全部...

取消回复欢迎 发表评论:

请填写验证码