Lambda

https://www.cnblogs.com/qdhxhz/p/9393724.html

https://blog.csdn.net/qq_21583077/article/details/88706645

https://www.jb51.net/article/160005.htm

https://mp.weixin.qq.com/s/TjetWEvJsSbJ9N-51ECkbw

1、什么是Lambda表达式

Lambda 表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。

它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 语言的表达能力得到了提升。

2、Lambda表达式的语法

基本语法:  (parameters) -> expression

     或者:(parameters) ->{ statements; 

举例说明:

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

3、什么是函数式接口

  再对上面进行举例说明之前,必须先来理解下函数式接口,因为Lambda是建立在函数式接口的基础上的。

 记住!

   (1)只包含一个抽象方法的接口,称为函数式接口

  (2)你可以通过 Lambda 表达式来创建该接口的对象。

  (3)我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检测它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。

在实际开发者有两个比较常见的函数式接口:Runnable接口,Comparator接口

public class Test {
    
    public static void main(String[] args) {
        
        // 1.1使用匿名内部类  
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                System.out.println("Hello world !");  
            }  
        }).start();  
          
        // 1.2使用 lambda 获得Runnable接口对象  
        new Thread(() -> System.out.println("Hello world !")).start();  
        
//=============================================================================
        
        // 2.1使用匿名内部类  
        Runnable race1 = new Runnable() {  
            @Override  
            public void run() {  
                System.out.println("Hello world !");  
            }  
        };  
          
        // 2.2使用 lambda直接获得接口对象 
        Runnable race2 = () -> System.out.println("Hello world !");          
        
        // 直接调用 run 方法(没开新线程哦!)  
        race1.run();  
        race2.run();  
    }
}
/*输出结果
 * Hello world !
 * Hello world !
 * Hello world !
 * Hello world !
 */

通过上面案例可以看出:通过Lambda表达式看去舒服清爽多了,而通过匿名内部类代码总是不够整洁。

再举一个例子:使用Lambda对数组排序

public class TestArray {
    
    public static void main(String[] args) {
        String[] players = {"zhansgan", "lisi", "wangwu", "zhaoliu",  "wangmazi"};  

        // 1.1 使用匿名内部类根据 surname 排序 players  
        Arrays.sort(players, new Comparator<String>() {  
            @Override  
            public int compare(String s1, String s2) {  
                return (s1.compareTo(s2));  
            }  
        });  
        
        // 1.2 使用 lambda 排序,根据 surname  
        Arrays.sort(players, (String s1, String s2) ->  s1.compareTo(s2));  
         
//================================================================================================
          
        // 2.1 使用匿名内部类根据 name lenght 排序 players  
        Arrays.sort(players, new Comparator<String>() {  
            @Override  
            public int compare(String s1, String s2) {  
                return (s1.length() - s2.length());  
            }  
        });  

        // 2.2使用Lambda,根据name length  
        Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));  
    
//==================================================================================================    
        
        // 3.1 使用匿名内部类排序 players, 根据最后一个字母  
        Arrays.sort(players, new Comparator<String>() {  
            @Override  
            public int compare(String s1, String s2) {  
                return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));  
            }  
        });  

        // 3.2 使用Lambda,根据最后一个字母
        Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));  
    }
}

通过上面例子我们再来思考为什么Lambda表达式需要函数式接口?其实很简单目的就是为来保证唯一

你的Runnable接口只要一个抽象方法,那么我用() -> System.out.println("Hello world !"),就只能代表run方法,如果你下面还有一个抽象方法,那我使用Lambda表达式,那鬼才知道要调用哪个抽象方法呢。

 

Lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。

流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。 我们先从最简单的示例来介绍Lambda表达式。

①用Lambda表达式实现Runnable:

    @Test
    public void test1(){
        //使用Java8之前
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("使用Lambda表达式之前,需要这么写!");
            }
        }).start();
        //使用Lambda表达式
        new Thread(() -> System.out.println("使用Lambda表达式,只需要这一句话!")).start();
    }

②使用Lambda表达式进行事件处理:

 

。。。。。

 


 

 Lambda结合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代码变的更加简洁!

利用函数式接口包

用Iterable.forEach()取代foreach loop

利用stream()替代静态函数

如果是println(p),则可以利用Method reference代替forEach中的Lambda表达式

Lambda配合Optional可以使Java对于null的处理变的异常优雅

我们现在就来对比一下下面四种常见的null处理中,Java 8的Lambda+Optional和传统Java两者之间对于null的处理差异。

 

 

 

posted @ 2019-10-30 20:02  Nausicaa0505  阅读(238)  评论(0编辑  收藏  举报