java8新特性:Lambda表达式【详细】

一、Lambda表达式介绍

1.1概念

Java8里面最重要的一个技术就是:Lambda表达式(也称闭包)。

Lambda允许把一个函数作为一个方法的入参。

使用场景:简化代码(接口的实现),例如:

public class DemoController {
    public static void main(String[] args) {
        ITest test = () -> {
            System.out.println("lambda表达式");
        };
        test.test1();
    }
}

interface ITest{
    void test1();
}

注意:并不是所有接口都能用Lambda表达式,Lambda表达式也只是一个匿名方法,且只能实现函数式接口。

函数式接口:一个接口中,有且仅有一个抽象方法。例如:

// 我们也可以用 @FunctionalInterface 来标注它是一个函数式接口。
interface ITest{
    void test1();
}

@FunctionalInterface:是⼀个注解,用在接口之前,判断这个接口是否是⼀个函数式接口。 如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。功能类似于 @Override

1.2基础语法

Lambda表达式就是一个匿名函数,不关注方法名,只关注参数和方法体。

Lambda表达式组成三要素:括号,箭头,代码块

(参数类型1 参数1,参数类型2 参数2,…) -> {
方法体
};

进阶:

  1. 参数类型与接口中写的方法的参数类型一致,可以省略不写(全部参数类型省略)。
  2. 参数只有一个时,小括号可以省略不写。
  3. 方法体只有一句语法时,大括号可以省略不写,如果有返回值,return关键字也可以去掉。

例如:

public class DemoController {
    public static void main(String[] args) {
        ITest test = name -> System.out.println("lambda表达式");
        test.test1();
    }
}

interface ITest{
    void test1(String name);
}

1.3方法引用

函数引用: 引用⼀个已经存在的方法,使其替代lambda表达式完成接口的实现

  1. 静态方法的引用

语法:类::静态方法

public class DemoController {
    public static void main(String[] args) {
        TriFunction<String, String, String, String> replace = StringUtils::replace;
        String s = replace.apply("abc", "a", "c");
        System.out.println(s);//cbc
    }
}

@FunctionalInterface
interface ITest{
    void test1();
}
  1. 非静态方法的引用

语法:对象::非静态方法

public class DemoController {
    public static void main(String[] args) {
        Function<String, String> test3 = new Test2()::test3;
        System.out.println(test3.apply("xiaoming"));
    }
}

class Test2{
     public String test3(String name){
         System.out.println("test2");
         return name;
     }
}

​ 3.构造方法的引用

语法:类名::new

public class DemoController {
    public static void main(String[] args) {
        // 引用指向Test3对象,
        GetTest3Param test3Param = Test3::new;
        Test3 test3 = test3Param.get("xiaoming");
        System.out.println(test3.getName());
    }

}

class Test3{
    private String name;
     Test3(String name){
         this.name=name;
     }

    public String getName() {
        return name;
    }
}

// 用于获取有参的对象
@FunctionalInterface
interface GetTest3Param{
    // 获取Test3对象
    Test3 get(String name);
}

1.4变量的作用域

lambda 表达式只能引用标记了 final 的外层局部变量,说明不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

public class DemoController {
    public static void main(String args[]) {
        // num如果不是被final修饰,lambda表达式内部不能修改num值,与匿名内部类中相同
        final int num = 1;
        Converter<Integer, String> s = (param) -> 
            System.out.println(String.valueOf(param + num));
        s.convert(2);  // 输出结果为 3
    }
 
    public interface Converter<T1, T2> {
        void convert(int i);
    }
}

lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

1.5Lambda表达式和匿名内部类的区别

  1. 所需类型不同

匿名内部类可以是:接口、抽象类、或者具体类
Lambda 表达式只能是:接口

  1. 使用限制不同

匿名内部类:接口中可以多个或者一个方法
Lambda 表达式要求:接口中的只能有一个方法

  1. 实现原理不同

查看项目文件夹中的时候可以看到

匿名内部类:编译之后会产生单独的 .class 文件
Lambda 表达式:编译之后不会有单独的 .class 文件出现,对应的字节码会在运行的时候动态生成。

二、Lambda表达式的使用

2.1集合中使用

Lambda表达式可以与Java 8的新集合操作方法(如stream()和forEach())一起使用,使集合的处理更加简单、灵活和易于读写。

public static void main(String[] args) {
    List<String> colour = Arrays.asList("blue", "red", "yellow");
    colour.stream().forEach(c -> System.out.println("颜色:"+c));
}

2.2多线程中使用

Lambda表达式可以与Java中的函数式接口一起使用

new Thread(() ->{
    // 异步执行任务
    System.out.println("1");
});

2.3排序

Lambda表达式可以用于Java中的排序算法中

public static void main(String[] args) {
    List<String> colour = Arrays.asList("blue", "red", "yellow");
    Collections.sort(colour,(p1,p2) -> p1.length() -p2.length());
    System.out.println(colour);
}

2.6过滤

Lambda表达式可以用于过滤集合中的元素

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> after = numbers.stream().filter(n -> n % 2 != 0).collect(Collectors.toList());

2.7映射

Lambda表达式可以用于将一个集合中的元素映射到另一个集合中

List<String> colours = Arrays.asList("blue", "red", "yellow");
List<String> upperCaseyellows = colours.stream().map(String::toUpperCase).collect(Collectors.toList());

2.8聚合

Lambda表达式可以用于聚合集合中的元素,例如,计算集合中的元素之和、平均值、最大值、最小值等。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 从0开始累加
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println("Sum of numbers: " + sum);

2.9函数式编程

有一个接口,其中包含一个抽象方法,需要在程序中实现该接口并调用该方法。可以使用以下代码将Lambda表达式作为接口实现传递给该方法

interface MyInterface {
    int doSomething(int x, int y);
}
 
MyInterface myLambda = (x, y) -> x + y;
int result = myLambda.doSomething(3, 4);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值