• Java lambda 表达式详解(JDK 8 新特性)


    什么是 lambda 表达式

    lambda 表达式(拉姆达表达式)是 JAVA 8 中提供的一种新的特性,它使 Java 也能进行简单的“函数式编程”。

    lambda 表达式的本质就是一个匿名方法(即没有方法名的方法)

    lambda 表达式使用案例

    1. 使用 lambda 表达式实现 Runnable
    package com.lambda;
    
    /**
     * 使用lambda表达式替换Runnable匿名内部类
     * @author MingChenchen
     *
     */
    public class RunableTest {
        /**
         * 普通的 Runnable
         */
        public static void runSomeThing(){
    
            Runnable runnable = new Runnable() {
    
                @Override
                public void run() {
                    System.out.println("I am running");
                }
            };
            new Thread(runnable).start();
        }
    
        /**
         * 使用lambda后的
         */
        public static void runSomeThingByLambda(){
            new Thread(() -> System.out.println("I am running")).start();
        }
    
        public static void main(String[] args) {
            runSomeThing();
    //      runSomeThingByLambda();
        }
    }
    

    上述代码中 () -> System.out.println("I am running")就是一个lambda表达式,可以看出,它是替代了new Runnable(){}这个匿名内部类。

    1. 使用 lambda表达式 实现 Comparator
    package com.lambda;
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    public class SortList {
        //给入一个List
        private static List<String> list = 
                Arrays.asList("my","name","is","uber","and","uc");
    
        /**
         * 对一个String的list进行排序 - 使用老方法
         */
        public static void oldSort(){
            //排序
            Collections.sort(list,new Comparator<String>() {
                //使用新的排序规则 根据第二个字符进行逆序排
                @Override
                public int compare(String a,String b){
                    if (a.charAt(1) <= b.charAt(1)) {
                        return 1;
                    }else{
                        return -1;
                    }
                }
            });
        }
    
        /**
         * 新的排序方法 - 使用lambda表达式实现
         */
        public static void newSort(){
            //lambda会自动推断出 a,b 的类型
            Collections.sort(list, (a, b) -> a.charAt(1) < b.charAt(1) ? 1:-1);
        }
    
        public static void main(String[] args) {
    //      oldSort();
            newSort();
        }
    }
    
    1. 使用 lambda 表达式实现 ActionListener
    package com.lambda;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    
    public class ActionEventDemo {
        private JButton button = new JButton();
    
    
        public void bindEvent(){
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("你好!" );
    
                }
            });
        }
    
        /**
         * 使用Lambda表达式 为button添加ActionListener
         */
        public void bindEventByLambda(){
            button.addActionListener(e -> System.out.println("你好!"));
        }
    }
    

    lambda 表达式的由来

    通过上述的几个例子,大家差不多也能明白了 lambda 表达式是用来干什么以及好处了。

    显而易见的,好处就是代码量大大减少了!程序逻辑也很清晰明了。

    它的用处浅显来说就是替代“内部匿名类”、可以对集合或者数组进行循环操作。

    因此,JDK 8 中就提供了这种 lambda 表达式,供我们来更加简明扼要的实现内部匿名类的功能。

    何时使用 lambda 表达式

    lambda 表达式的本质是一个匿名方法,那就是说当你只需要一个能做一件事情的方法而已,连方法叫什么名字都无关紧要,Lambda 表达式就可以用来做这件事。

    lambda 表达式语法

    基本语法:
    (参数) -> 表达式

    (参数) -> { 代码块; }

    //1. 接收2个int型整数,返回他们的和
    (int x, int y) -> x + y;
    
    //2. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
    (String s) -> System.out.print(s);
    

    lambda 表达式特性

    类型推导

    编译器负责推导lambda表达式的类型。它利用lambda表达式所在上下文所期待的类型进行推导,
    这个被期待的类型被称为目标类型。就是说我们传入的参数可以无需写类型了!

    变量捕获

    在Java SE 7中,编译器对内部类中引用的外部变量(即捕获的变量)要求非常严格:
    如果捕获的变量没有被声明为final就会产生一个编译错误。
    我们现在放宽了这个限制——对于lambda表达式和内部类,
    我们允许在其中捕获那些符合有效只读(Effectively final)的局部变量。

    简单的说,如果一个局部变量在初始化后从未被修改过,那么它就符合有效只读的要求,
    换句话说,加上final后也不会导致编译错误的局部变量就是有效只读变量。

    注意:此处和final关键字一样,指的是引用不可改!(感觉没多大意义,还不是用的final)

    方法引用

    如果我们想要调用的方法拥有一个名字,我们就可以通过它的名字直接调用它。
    Comparator byName = Comparator.comparing(Person::getName);
    此处无需再传入参数,lambda会自动装配成Person类型进来然后执行getName()方法,而后返回getName()的String

    方法引用有很多种,它们的语法如下:
    静态方法引用:ClassName::methodName
    实例上的实例方法引用:instanceReference::methodName
    超类上的实例方法引用:super::methodName
    类型上的实例方法引用:ClassName::methodName
    构造方法引用:Class::new
    数组构造方法引用:TypeName[]::new

    JAVA提供给我们的SAM接口

    Java SE 8中增加了一个新的包:java.util.function,它里面包含了常用的函数式接口,例如:

    Predicate——接收T对象并返回boolean
    Consumer——接收T对象,不返回值
    Function<T, R>——接收T对象,返回R对象
    Supplier——提供T对象(例如工厂),不接收值
    UnaryOperator——接收T对象,返回T对象
    BinaryOperator——接收两个T对象,返回T对象

    那么在参数为这些接口的地方,我们就可以直接使用 lambda 表达式了!

    lambda 表达式优缺点

    优点
    • 极大的简化代码,去除了很多无用的 Java 代码,使得代码更为简洁明了
    缺点
    • 可读性差。在代码简洁的情况下,另一方面又让大多程序员很难读懂。因为很少程序员接触使用它。 (不过这个缺点不是本身缺点,而且源于程序员较少使用)

    总结

    lambda 表达式是 JDK 8 新特性,本质是一个匿名方法,可以简化代码,但代码可读性差。

    作者:Binge
    本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    org.hibernate.QueryException: could not resolve property
    Eclipse支持文件UTF-8编码
    Eclipse External Tool Configration Notepad++
    WIN10 devtoolsuser
    Linux查看和注销用户(User)
    java list 去重
    监控系统对比 Ganglia vs Open-falcon vs Prometheus vs Zabbix vs Nagios vs PandoraFMS
    swagger 指定字段不显示到文档里
    mysql uuid() 相同 重复
    正则校验:微信号,qq号,邮箱
  • 原文地址:https://www.cnblogs.com/binbingg/p/13673090.html
Copyright © 2020-2023  润新知