JavaLambda表达式详解

2023-02-20 09:07:18

Java Lambda表达式是JDK8引入的,是一个比较重要的特性

Lambda表达式简介

Lambda>

Lambda表达式可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

Lambda表达式的作用

Java>

怎么一个简化优雅呢,举一Lambda语法创建线程和匿名内部类创建线程的例子,就非常清楚了。

1.匿名类创建线程

// JDK7匿名内部类写法
new Thread(new Runnable() {//接口名
        @Override
        public void run() {//方法名
            System.out.println("mikechen");
        }
    });

2.Lambda表达式创建线程

// JDK8 Lambda来创建线程
new Thread(() -> System.out.println("mikechen"));

上述代码跟匿名内部类的作用是一样的,但比匿名内部类更进一步,这里连接口名和函数名都一同省掉了,Lambda表达式可以取代匿名内部类,写出更优雅的代码。

Lambda表达式的语法

lambda>

Java Lambda表达式详解(非常全面)-mikechen的互联网架构

    ():左侧部分指定了Lambda表达式需要的所有参数。->:Lambda表达式的操作符或者箭头操作符。{}:右侧部分指定了Lambda体,即方法需要实现的内容。

    Java Lambda表达式详解(非常全面)-mikechen的互联网架构

    1.无参数

    Lambda体只有一条语句:

    示例:

    () -> System.out.println("mikechen");

    请注意,括号中没有内容。那就是表示lambda不带任何参数。

    2.一个参数

    示例:

    Consumer<String> con = (x) -> System.out.println(x);

    当lambda表达式是单个参数时,也可以省略括号,如下所示:

    Consumer<String> con = x -> System.out.println(x);

    3.多个参数

    如果Java>

    BinaryOperator<Integer> bo = (a, b) -> {
        System.out.println("函数式接口");
        return a + b;
    };

    注意:仅当方法是单个参数时,才可以省略括号。

    4.指定参数类型

    如果编译器无法从lambda匹配的函数式接口抽象方法推断参数类型,则有时可能需要为lambda表达式指定参数类型。

    (Car car) -> System.out.println("The car is: " + car.getName());

    如你所见,car参数的类型(Car)写在参数名称的前面,就像在其他方法中声明参数或对接口进行匿名实现时一样。

    5.只有一条语句时

    当Lambda体只有一条语句时,return和大括号可以省略,示例:

    BinaryOperator<Integer> bo = (a, b) -> a + b;

    6.参数类型不写

    Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器能够通过上下文推断出数据类型,这就是“类型推断”,示例:

    BinaryOperator<Integer> bo = (Integer a, Integer b) -> {
        return a + b;
    };

    等同于

    BinaryOperator<Integer> bo = (a, b) -> {
        return a + b;
    };

    上述 Lambda 表达式中的参数类型都是由编译器推断得出,Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。

    Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的,这就是所谓的“类型推断”。

    7.Lambda表达式返回值

    你可以从Java>

    (param) -> {
        System.out.println("param: " + param);
        return "return value";
    }

    函数式接口

    Lambda表达式需要函数式接口的支持,所以,我们有必要来说说什么是函数式接口。

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FunctionalInterface {}

    一种用于表示一个接口是Java语言规范定义的函数式接口的注解类型。

    对于函数式接口,我们可以理解为只有一个抽象方法的接口,除此之外它和别的接口相比并没有什么特殊的地方。

    public interface MyFunctionInterface<T> {
        public T getValue(T t);
    }

    为了确保函数式接口的正确性,我们可以给这个接口添加@FunctionalInterface注解,这样当其中有超过一个抽象方法时就会报错。

    Unexpected @FunctionalInterface annotation
    @FunctionalInterface ^ WorkerInterface is not a functional interface multiple
    non-overriding abstract methods found in interface WorkerInterface 1 error

    Java 8中每一个Lambda表达式必须有一个函数式接口与之对应,也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。

    Lambda表达式的举例

    学习>

    1.lambda创建线程

    使用()>

    //JDK 8之前
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("使用匿名内部类,开线程");
        }
    }).start();
    
    //JDK 8 使用lambda表达式
    new Thread(() -> System.out.println("使用lambda表达式,开线程")).start();

    2.lambda事件处理

    使用lambda表达式如下所示写出更好的事件侦听器的代码:

    // Java 8之前:
    button.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Button被点击了使用老的方式!");
        }
    });
    
    // Java 8方式:
    button.addActionListener( (e) -> {
        System.out.println("Button被点击了使用Lambda表达式!");
    });

    3.lambda遍历List集合

    集合的遍历,采用lambda表达式会更简洁:

    // Java 8之前:
    List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
    for (String feature : features) {
        System.out.println(feature);
    }
    
    // Java 8之后:
    List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
    features.forEach(n -> System.out.println(n));
    
    // 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
    features.forEach(System.out::println);

    方法引用是使用两个冒号::这个操作符号。

    4.元素排序

    之前我们若要为集合内的元素排序,就必须调用>

    方法的比较器对象,现在我们还可以使用 lambda 表达式来简化代码。

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("d");
        list.add("b");
        list.add("c");
        list.sort((o1,o2)->o1.compareTo(o2));
        list.forEach(System.out::println);
    }

    5.lambda>
    // 不使用lambda表达式为每个订单加上12%的税
    List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    for (Integer cost : costBeforeTax) {
        double price = cost + .12*cost;
        System.out.println(price);
    }
    // 使用lambda表达式
    List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);

    6.lambda过滤String

    // 创建一个字符串列表,每个字符串长度大于2
    List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
    System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);

    7.lambda对集合应用函数

    // 将字符串换成大写并用逗号链接起来
    List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
    String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
    System.out.println(G7Countries);

    8.lambda计算最大值、最小值、平均值

    //获取数字的个数、最小值、最大值、总和以及平均值
    List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
    IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("Highest prime number in List : " + stats.getMax());
    System.out.println("Lowest prime number in List : " + stats.getMin());
    System.out.println("Sum of all prime numbers : " + stats.getSum());
    System.out.println("Average of all prime numbers : " + stats.getAverage());

    以上就是Java Lambda表达式详解的详细内容,更多关于Java Lambda表达式详解的资料请关注易采站长站其它相关文章!