Lambda 表达式

41 篇文章 2 订阅

目录

1. 为什么要使用Lambda

2. Lambda语法

3. Lambda基础使用

4. Lambda和函数式接口

  4.1 函数式接口

5. Lambda的变量获取

6. Lambda在集合中的使用

6.1 Map 中的 forEach

6.2 List 排序

6.3 List 查找

7. Lambda优缺点


1. 为什么要使用Lambda

Lambda 表达式是 JDK 8 中⼀个重要的新特性,lambda 表达式允许通过表达式来代替功能接⼝(通过表达式通过实现业务功能)。lambda 表达式就和⽅法⼀样,它提供了⼀个正常的参数列表和⼀个使⽤这些参数的主体(body,可以是⼀个表达式或⼀个代码块),Lambda 表达式(Lambda expression)可以看作是⼀个匿名函数。

        1. 提供了更简单的语法和写代码的⽅式。
        2. 取代匿名内部类。
        3. 简化代码,⼲净整洁。

2. Lambda语法

Lambda 表达式的基本语法如下:
(参数列表) -> {业务代码实现}

表达式由 3 部分组成:

        1. 参数列表:类似⽅法中的形参列表,这⾥的参数是函数式接⼝⾥的参数。这⾥的参数类型可以明确的声明也可不声明⽽由JVM隐含的推断。另外当只有⼀个推断类型时可以省略掉圆括号。

        2. ->  表示被用于,不可以省略 。

        3. 代码实现:可以是表达式也可以代码块,是函数式接⼝⾥⽅法的实现。代码块可返回⼀个值或者什么都不反回,这⾥的代码块块等同于⽅法的⽅法体。如果是表达式,也可以返回⼀个值或者什么都不返回。

3. Lambda基础使用

import java.util.Arrays;
import java.util.List;
public class LambdaExample {
    public static void main(String[] args) {
        List<String> lists = Arrays.asList("Hello", "World", "Java");
        // 没使⽤ lambda 之前
        for (String list : lists) {
            System.out.println(list);
       }
        System.out.println();
        // 使⽤ lambda 之后
        lists.forEach(s -> System.out.println(s));
   }
}


// 输出: hello world Java
          hello world Java
注意事项:
         1. 如果 lambda 参数的⼩括号⾥⾯只有⼀个参数,那么⼩括号可以省略。
        2. 如果⽅法体当中只有⼀句代码,那么⼤括号可以省略。
        3. 如果⽅法体中只有⼀条语句,其是 return 语句,那么⼤括号可以省略,且去掉 return 关键字。

 

4. Lambda和函数式接口

Lambda 表达式的写法:
// 1. 不需要参数 , 返回值为 2
() -> 2
// 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 )
Lambda 表达式不能直接使⽤,它在使⽤之前必须初始化,lambda 表达式必须借助函数式接⼝
(@FunctionalInterface)来初始化。

  4.1 函数式接口

        函数式接⼝定义:⼀个接⼝有且只有⼀个抽象⽅法。
注意事项:
         1. 如果⼀个接⼝只有⼀个抽象⽅法,那么该接⼝就是⼀个函数式接⼝。
         2. 如果我们在某个接⼝上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接⼝的定义来要求该接⼝,这样如果有两个抽象⽅法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接⼝中只有⼀个抽象⽅法,你可以不加这个注解。加上就会⾃动进⾏检测的。

函数式接⼝的定义代码如下:

@FunctionalInterface
interface MyFunctionalInterface {
    void myMethod(Object... args);
}

 有了函数式接⼝之后,我们就可以使⽤ lambda 表达式对其实例化了,实现代码如下:

@FunctionalInterface
interface MyFunctionalInterface {
    void myMethod(Object... args);
}
public class LambdaExample {
    public static void main(String[] args) {
        // lambda 表达式借助函数式接⼝初始化
        MyFunctionalInterface functionalInterface = (objects) -> {
            for (Object o : objects) {
                System.out.println(o.toString());
           }
       };
        // 执⾏ lambda 表达式
        functionalInterface.myMethod("张三", "李四", "王五");
   }
}

// 输出: 张三 李四 王五

5. Lambda的变量获取

在 lambda 中,如果要获取外部的 变量,那么这个变量要么是被 final 修饰,如果不是被 final 修饰的,要保证在使⽤之前,没有修改,否则就会报错。
@FunctionalInterface
interface MyFunctionalInterface {
    void myMethod(Object... args);
}
public class LambdaExample {
    public static void main(String[] args) {
        int count = 10;
        MyFunctionalInterface functionalInterface = (objects) -> {
            // count = 99; // 在使⽤之前,如果修改就会报错
            for (Object o : objects) {
                System.out.println(o.toString());
           }
            System.out.println("打印外部变量:" + count); // 可以正常执⾏
       };
        functionalInterface.myMethod("张三", "李四", "王五");
   }
}

6. Lambda在集合中的使用

Lambda 表达式最有价值的作⽤就是可以配合集合⼀块使⽤。
Lambda 可以配合使⽤的⽅法列表如下:

6.1 Map 中的 forEach

在没有 Lambda 之前,我们要循环 Map 的实现代码如下:

import java.util.HashMap;
import java.util.Map;
public class LambdaExample {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap() {{
            put("name", "Java");
            put("desc", "Good");
       }};
        // jdk 8 之前的写法
        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
       }
   }
}

// 输出: name : Java   desc : Good

有了 lambda 之后,我们可以这样写:

import java.util.HashMap;
public class LambdaExample {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap() {{
            put("name", "Java");
            put("desc", "Good");
       }};
        map.forEach((k, v) -> System.out.println(k + ":" + v));
   }
}

// 输出: name : Java   desc : Good

 

6.2 List 排序

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class LambdaExample {
   public static void main(String[] args) {
       List<Integer> lists = new ArrayList() {{
           add(1);
           add(5);
           add(3);
           add(2);
           add(6);
        }};
       System.out.println(lists); // 排序前顺序 [1, 5, 3, 2, 6]
       lists.sort(new Comparator<Integer>() {
           @Override
           public int compare(Integer o1, Integer o2) {
               return o1 - o2; // 正序
            }
        });
       System.out.println(lists);
    } 
}

// 输出: 1 5 3 2 6      1 2 3 4 5 6

6.3 List 查找

List<String> lists = new ArrayList<String>() {{
    add("Java");
    add("MySQL");
    add("Spring");
}};

List<String> javaItem = lists.stream()
   .filter(s -> s.equals("Java")).collect(Collectors.toList());
System.out.println(javaItem);

// 输出: [Java]

7. Lambda优缺点

优点:
        1. 代码简洁,开发迅速
        2. ⽅便函数式编程
        3. ⾮常容易进⾏并⾏计算
        4. Java 引⼊ Lambda,改善了集合操作
缺点:
        1. 代码可读性变差
        2. 在⾮并⾏计算中,很多计算未必有传统的 for 性能要⾼
        3. 不容易进⾏调试
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值