站长家园(原代码之家)(www.adminjie.com)网站源码,微信源码,游戏源码,商业源码分享平台。
当前位置:网站首页 技术文章 网络编程 正文

Java实例详解之Lambda表达式

时间:2022-04-24 [网络编程]作者:fabuyuan 浏览:6 次

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于Lambda表达式的相关问题,Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符,下面一起来看一下,希望对大家有帮助

推荐学习:《java视频教程

一、Lambda初识

我们知道,在Java中,接口是不能实例化的,但是接口对象可以指向它的实现类对象。如果接口连实现对象都没有呢?那还可以使用匿名类的方式,如下:

public class JavaTest {
    public static void main(String[] args) {
        Fly fly = new Fly() {
            @Override
            public void fly(String name) {
                System.out.println(name + "飞行");
            }
        };
        fly.fly("张三");
    }}interface Fly{
    abstract void fly(String name);}

但是,使用匿名内部的方式,代码量其实并不是非常简洁,而为了使代码更加的简洁,Java引进了Lambda表达式的写法,通过更简单的语法,去实现这样功能,使用Lambda表达式简化的代码如下:

public class JavaTest {
    public static void main(String[] args) {
        Fly fly = name -> System.out.println(name + "飞行");
        fly.fly("张三");
    }}interface Fly{
    abstract void fly(String name);}

通过Lambda表达式完成了同样的效果,但是代码量却精简了非常对,这就是Lambda表达式的魅力。

二、 函数式接口

在学习Lambda表达式的语法之前,首先要知道什么是函数式接口, 只有一个待实现方法 的接口,就叫做函数式接口。

//接口中只有一个待实现的方法 fly,所以这是函数式接口interface Fly{
     void fly(String name);}//接口中有两个待实现的方法 这是不是函数式接口interface Run{
    void fastRun();
    void slowRun();}//接口中有两个方法,但其中一个是已经定义好的default方法,真正需要子类去实现的方法只有一个 这是函数式接口interface Jump{
    void jump();
    default void highJump(){
        System.out.println("跳的更高");
    }}

可以在接口上加**@FunctionalInterface注解,去断言这个接口是函数式接口,如果这个接口不是函数式接口,编译就会提示错误。

为什么要知道什么是函数式接口呢?因为Lambda表达式去简化一个接口的匿名类实现方式,它只
能对函数式接口起作用**。
这很容易理解,如果一个接口有多个待实现的方法,Lambda表达式就不能分辨出它现在是对接口中哪个方法进行实现。

三、Lambda表达式语法

Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

左侧:指定了Lambda表达式需要的所有参数
右侧:制定了Lambda体,即Lambda表达式要执行的功能。
像这样:

(parameters) -> expression
或
(parameters) ->{ statements; }

Lambda表达式的除了->和Lambda体,其他的比如参数,小括号,中括号都是可以更加参数类型、方法体代码行数进行省略的。
以如下函数式接口的实现为例:

interface MathOperation {
        int operation(int a, int b);
    }

    interface GreetingService {
        void sayMessage(String message);
    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }
    
    interface NoParam{
        int returnOne();
    }

以下是lambda表达式的重要特征:

  • 可选类型声明:Lambda表达式可以不用声明实现方法的参数类型,编译器可以统一识别参数值。
        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;
        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;
  • 可选的参数圆括号:一个参数无需定义圆括号,但没有参数或者多个参数需要定义圆括号。
      // 不用括号
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

        // 用括号
        GreetingService greetService2 = (message) ->
                System.out.println("Hello " + message);
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
     // 多条语句不可以省略大括号
        MathOperation multiplication = (int a, int b) -> {
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略大括号
        MathOperation pision = (int a, int b) -> a / b;
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
  // 多条语句的Lambda表达式如果有返回值,需要使用return
        MathOperation multiplication = (int a, int b) -> {
            int num = a+1;
            num = a + b;
            return a * b + num;
        };

        // 单条语句可以省略return
        MathOperation pision = (int a, int b) -> a / b;

四、Lambda表达式的使用范围

Lambda表达式并不只是单单的用来简化一个匿名类的创建,它还有更多的用法。

1、为变量赋值

上文中,对Lambda表达式的用法都是为变量赋值的写法,这样可以简化匿名内部类赋值的代码段,提高阅读效率。

MathOperation subtraction = (a, b) -> a - b;

2、作为return结果

interface MathOperation {
        int operation(int a, int b);
    }

    MathOperation getOperation(int a, int b){
        return (a1, b1) -> a+b;
    }

3、作为数组元素

MathOperation math[] = {
                (a,b) -> a+b,
                (a,b) -> a-b,
                (a,b) -> a*b        };

4、作为普通方法或者构造方法的参数

public static void main(String args[]){

        Java8Tester java8Tester = new Java8Tester();
        java8Tester.operate(1,2,((a, b) -> a*b));

    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }

    interface MathOperation {
        int operation(int a, int b);
    }

五、Lambda表达式的作用域范围

Lambda表达式表达体内,可以访问表达体外的变量,但无法对其他变量进行修改操作。

六、Lambda表达式的引用写法

在学习Lambda的时候,还可能会发现一种比较奇怪的写法,例如下面的代码:

// 方法引用写法GreetingService greetingService = System.out::println;
        greetingService.sayMessage("hello world");

这里出现了一个从来没见过的符号 :: ,这种写法就叫做方法的引用。
显然使用方法引用比普通的Lambda表达式又简洁了一些。

如果函数式接口的实现恰好可以通过调用一个方法来实现,那么我们可以使用方法引用。

public class Java8Tester {


    public static void main(String args[]){

        // 静态方法引用--通过类名调用
        GreetingService greetingService = Test::MyNameStatic;
        greetingService.sayMessage("hello");
        Test t = new Test();
        //实例方法引用--通过实例调用
        GreetingService greetingService2 = t::myName;
        // 构造方法方法引用--无参数
        Supplier<Test> supplier = Test::new;
        System.out.println(supplier.get());
    }



    interface GreetingService {
        void sayMessage(String message);
    }}class Test {
    // 静态方法
    public static void MyNameStatic(String name) {
        System.out.println(name);
    }

    // 实例方法
    public void myName(String name) {
        System.out.println(name);
    }

    // 无参构造方法
    public Test() {
    }}

7、Lambda表达式的优缺点

优点:

  • 更少的代码行-lambda表达式的最大好处之一就是减少了代码量。我们知道,lambda表达式只能与功能接口一起使用。例如,Runnable 是一个接口,因此我们可以轻松地应用lambda表达式。

  • 通过将行为作为方法中的参数传递来支持顺序和并行执行-通过在Java 8中使用Stream API,将函数传递给collection方法。现在,集合的职责是以顺序或并行的方式处理元素。

  • 更高的效率-过使用Stream API和lambda表达式,可以在批量操作集合的情况下获得更高的效率(并行执行)。 此外,lambda表达式有助于实现集合的内部迭代,而不是外部迭代。

缺点

  • 运行效率-若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势)
  • 很难调试-Lambda表达式很难打断点,对调式不友好。
  • 不容易看懂-若其他程序员没有学过 lambda 表达式,代码不容易让其他语言的程序员看懂(我学Lambda表达式的原因是看不懂同事写的Lambda表达式代码)

推荐学习:《java视频教程》

以上就是Java实例详解之Lambda表达式的详细内容,更多请关注站长家园其它相关文章!

本文标签:  java

转载请注明来源:Java实例详解之Lambda表达式

本文永久链接地址:https://www.adminjie.com/post/11577.html

免责声明:
本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

附:
二○○二年一月一日《计算机软件保护条例》第十七条规定:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬!鉴于此,也希望大家按此说明研究软件!

版权声明:
一、本站致力于为软件爱好者提供国内外软件开发技术和软件共享,着力为用户提供优资资源。
二、本站提供的部分源码下载文件为网络共享资源,请于下载后的24小时内删除。如需体验更多乐趣,还请支持正版。
三、我站提供用户下载的所有内容均转自互联网。如有内容侵犯您的版权或其他利益的,若有侵犯你的权益请:提交版权证明文件到邮箱 2225329873#qq.com(#换为@) 站长会进行审查之后,情况属实的会在三个工作日内为您删除。

  • 站长家园(原代码之家)会员升级
  • 最新文章
    • 完全掌握java之String类

      完全掌握java之String类

      本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于string类的相关问题,包括了字符串的常量池、字符串的不可变性等等相关内容,下面一起来看一下,希...

    • 简单学习Python字符和列表(实例详解)

      简单学习Python字符和列表(实例详解)

      本篇文章给大家带来了关于python的相关知识,其中主要介绍了关于字符和列表的相关问题,包括了字符串的输入输出、列表循环遍历、列表的增删改查以及列表的嵌套等等内...

    • 图文解析Redis线程模型

      图文解析Redis线程模型

      本篇文章给大家带来了关于Redis的相关知识,其中主要介绍了关于线程模型的相关问题,Redis它是一个单线程的,下面就一起来看一下,希望对大家有帮助。推荐学习:...

    • jquery怎么判断元素是否有子节点

      jquery怎么判断元素是否有子节点

      方法:1、用children()获取元素下的所有子节点,语法“元素对象.children()”,会返回一个包含子节点的jQ对象;2、用length检测子节点个数...

    • jquery对象访问的方法有哪些

      jquery对象访问的方法有哪些

      jquery对象访问的方法有:1、each(),可以遍历指定的jquery对象,语法“$.each(对象,回调函数)”;2、size(),可统计jquery对象...

    热门文章