前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java8 Lambda

Java8 Lambda

原创
作者头像
HLee
修改2021-09-14 10:55:05
5310
修改2021-09-14 10:55:05
举报
文章被收录于专栏:房东的猫房东的猫

简介

Lambda的语法极为简单(Lambda表达式的前置条件:必须是“函数式接口”),类似如下结构:

代码语言:javascript
复制
无参:() -> expression;
有参:(parameters) -> expression;
有参:(parameters) -> { statements; };

Lambda表达式由三部分组成:

  • paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断,另外当只有一个推断类型时可以省略掉圆括号。
  • ->:可理解为“被用于”的意思
  • 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

Lambda

接口的抽象方法有几种场景,我们来看一下

代码语言:javascript
复制
无参数、无返回值
public void print(){
	// 函数式接口的方法实现
	System.out.println("Hello Lambda!");
} 

Lambda表达式写法

() -> System.out.println("Hello Lambda!");
代码语言:javascript
复制
1个参数,无返回值
public void print(String str){
	// 函数式接口的方法实现
	System.out.println("Hello " + str);
}

Lambda的写法

(str) -> System.out.println("Hello " + str);
如果是1个参数,可以去掉小括号
str -> System.out.println("Hello " + str);
代码语言:javascript
复制
多个参数、有返回值,且多条语句
public int add(int x,int y){
	// 函数式接口的方法实现
	System.out.println("执行加法运算!");
    return x+y;
} 

Lambda的写法

(x, y) -> {
  System.out.println("执行加法运算!");
  return x+y;
}
此处因为是多条语句,所以一定要用花括号。
代码语言:javascript
复制
多个参数,有返回值,且一条语句,省掉花括号以及return
public int add(int x,int y){
	// 函数式接口的方法实现
	return x + y;
} 

用Lambda表达式可以写成

(x, y) -> x + y;

测试用例

例如:自定义一个排序器,实现compare函数(函数式接口Comparator唯一的抽象方法)。返回0表示元素相等,-1表示前一个元素小于后一个元素,1表示前一个元素大于后一个元素。这个规则和java 8之前没什么区别。

下面代码用自定义接口实现类的的方式实现:按照年龄的倒序排序

代码语言:javascript
复制
employees.sort(new Comparator<Employee>() {
    @Override
    public int compare(Employee em1, Employee em2) {
        if(em1.getAge() == em2.getAge()){
            return 0;
        }
        return em1.getAge() - em2.getAge() > 0 ? -1:1;
    }
});
employees.forEach(System.out::println);

如果以lambda表达式简写。箭头左侧是参数,右侧是函数体,参数类型和返回值根据上下文自动判断。如下:

代码语言:javascript
复制
employees.sort((em1,em2) -> {
    if(em1.getAge() == em2.getAge()){
        return 0;
    }
    return em1.getAge() - em2.getAge() > 0 ? -1:1;
});
employees.forEach(System.out::println);

例:自定义一个lambada表达式

代码语言:javascript
复制
public class LambdaTest {

    interface Printer{
        void print(String sys);
    }

    public void printSome(String str, Printer printer) {
        printer.print(str);
    }

    public static void main(String[] args) {

        LambdaTest lambdaTest = new LambdaTest();

        // 普通实现方式
//        Printer printer = new Printer() {
//            @Override
//            public void print(String sys) {
//                System.out.println(sys);
//            }
//        };

        // lambada实现方式-左侧是参数,右侧是实现
//        Printer printer = (String sys) -> {
//            System.out.println(sys);
//        };

        // lambada实现方式(简化)
        Printer printer = sys -> System.out.println(sys);

        lambdaTest.printSome("我要打印......", sys -> System.out.println(sys)); // 函数式接口的方法实现
        lambdaTest.printSome("我要打印......", printer);

    }
}

参数传递

代码语言:javascript
复制
@FunctionalInterface
public interface Formatter {
    void format(String name, int age);
}
代码语言:javascript
复制
public class LambdaTest {

    public static void main(String[] args) {
        print((String name, int age)-> System.out.println(String.format("name:%s age:%d", name, age)), "ziyu", 18);
    }

    public static void print(Formatter formatter, String name, int age) {
        formatter.format(name, age);
    }
}

没有返回值

代码语言:javascript
复制
public class LambdaTest2 {

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello lambda");
            }
        }).start();

        new Thread(() -> System.out.println("hello lambda")).start();
    }
}

有返回值

代码语言:javascript
复制
public interface IdFactory {
    String generateId();
}
代码语言:javascript
复制
import java.util.UUID;

public class LambdaTest3 {

    public static void main(String[] args) {
        String name = getId(()-> UUID.randomUUID() + "");
        System.out.println(name);
    }

    static String getId(IdFactory factory) {
        return factory.generateId();
    }

}

方法引用

符号表示:::

符号说明:双冒号为方法引用运算符,而它所在的表达式被称为方法引用。

应用场景:如果Lambad表达式所要实现的方案,已经有其他方法存在相同的方案,那么则可以使用方法引用。

总结:方法引用是对Lambda表达式符合特定情况下的一种缩写形式,它使得我们的Lambda表达式更加精简,也可以理解为lambad表达式的缩写形式,不过要注意的是方法引用只能引用已经存在的方法。

代码语言:javascript
复制
public interface Calculator {
    int compute(int a, int b);
}
代码语言:javascript
复制
public class LambdaTest3 {

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        // 这里不能用 (a, b), 那样的话会产生歧义,使得编译器报错
        runIt((x, y)->{
            System.out.print(x);
            System.out.print(" + ");
            System.out.print(y);
            System.out.print(" = ");
            System.out.println(x + y);
            return x + y;
        }, a, b);
    }

    static void runIt(Calculator calculator, int a, int b) {
        calculator.compute(a, b);
    }
}

1. 静态方法引用

代码语言:javascript
复制
public class LambdaTest6 {

    static int sum(int x, int y) {
        // 函数式接口的方法实现
        System.out.println(x + y);
        return x + y;
    }

    static void runIt(Calculator calculator, int a, int b) {
        calculator.compute(a, b);
    }

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        runIt(LambdaTest6::sum, a, b);
    }
}
代码语言:javascript
复制
@Test
public void test() {

    Supplier<Long> supplier = () -> {
        return System.currentTimeMillis();
    };
    System.out.println(supplier.get());

    // 静态方法引用实现
    Supplier<Long> supplier1 = System::currentTimeMillis;
    System.out.println(supplier1);
}

2. 成员方法引用

如果一个类中已经存在一个成员方法,则可以通过对象名引用成员方法。

注意事项:

  • 被引用的方法的参数和接口中的抽象方法的参数一样;
  • 当接口抽象方法有返回值时,被引用的方法也必须有返回值;
代码语言:javascript
复制
public class LambdaTest7 {

    int sum(int x, int y) {
        // 函数式接口的方法实现
        System.out.println(x + y);
        return x + y;
    }

    static void runIt(Calculator calculator, int a, int b) {
        calculator.compute(a, b);
    }

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        runIt(new LambdaTest7()::sum, a, b);
    }
}

new LambdaTest7()::sum: 先新建对象LambdaTest7,并且通过该对象来使用成员变量引用

代码语言:javascript
复制
@Test
public void test() {

    Date now = new Date();

    Supplier supplier = () -> {return now.getTime();};
    System.out.println(supplier.get());

    // 方法引用实现
    Supplier supplier1 = now::getTime;
    System.out.println(supplier1.get());
}

3. 类名::引用实例方法

代码语言:javascript
复制
@Test
public void test() {

    Function<String, Integer> function = (s) -> {
        return s.length();
    };
    System.out.println(function.apply("hello"));

    // 通过方法引用来实现
    Function<String, Integer> function1 = String::length;
    System.out.println(function1.apply("hello"));
}

4. 类名::构造器引用

由于构造器的名称和类名完全一致,所以构造器引用使用::new的格式使用。

代码语言:javascript
复制
@Test
public void test() {

    Supplier supplier = () -> {return new Person();};
    System.out.println(supplier.get());

    // 通过方法引用来实现
    Supplier supplier1 = Person::new;
    System.out.println(supplier1.get());

    BiFunction<Long, String, Person> biFunction = Person::new;
    System.out.println(biFunction.apply(12L, "Tom"));
}

5. 数组::构造器

代码语言:javascript
复制
    @Test
    public void test() {

        Function<Integer, String[]> function = (len) -> {
            return new String[len];
        };
        String[] a = function.apply(3);
        System.out.println("数组的长度: " + a.length);

        // 方法的方式来调用数组的构造器
        Function<Integer, String[]> function1 = String[]::new;
        String[] a1 = function1.apply(3);
        System.out.println("数组的长度: " + a1.length);
    }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • Lambda
  • 测试用例
    • 参数传递
      • 没有返回值
        • 有返回值
          • 方法引用
            • 1. 静态方法引用
            • 2. 成员方法引用
            • 3. 类名::引用实例方法
            • 4. 类名::构造器引用
            • 5. 数组::构造器
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档