zoukankan      html  css  js  c++  java
  • 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
    本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    UVA 254 Towers of Hanoi
    UVA 701 The Archeologists' Dilemma
    UVA 185 Roman Numerals
    UVA 10994 Simple Addition
    UVA 10570 Meeting with Aliens
    UVA 306 Cipher
    UVA 10160 Servicing Stations
    UVA 317 Hexagon
    UVA 10123 No Tipping
    UVA 696 How Many Knights
  • 原文地址:https://www.cnblogs.com/binbingg/p/13673090.html
Copyright © 2011-2022 走看看