Lambda表达式:Java编程的简洁与强大

引言

随着Java 8的发布,Lambda表达式成为了Java编程语言中一个引人注目的新特性。Lambda表达式不仅简化了代码,还使得Java更加贴近于函数式编程的范式。本文将深入探讨Lambda表达式的概念、语法、应用场景以及它如何改变我们的编程方式。

什么是Lambda表达式?

Lambda表达式是一种匿名函数,它允许你以更简洁的方式表示只有一个抽象方法(即函数式接口)的接口的实例。简单来说,Lambda表达式就是一段可以传递的代码,它定义了一个操作的实现,但没有名称。

函数式接口

在Java中,Lambda表达式只能与函数式接口一起使用。函数式接口是只包含一个抽象方法的接口(可以有多个默认方法或静态方法)。Java 8引入了@FunctionalInterface注解,用于指示一个接口是函数式接口,但这不是强制性的,只要接口满足函数式接口的定义即可。

Lambda表达式的语法

Lambda表达式的基本语法如下:

(parameters) -> expression

或者对于包含多条语句的情况:

(parameters) -> { statements; }

其中,parameters是Lambda表达式接收的参数列表,->是Lambda操作符,expression或{ statements; }是Lambda体的实现。

示例:

//Java中用于函数式编程的几个关键接口
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
//BiFunction<T, U, R> - 接受两种类型的参数,并返回一个结果。
import java.util.List;
import java.util.function.BiFunction;
//BinaryOperator<T> - 是BiFunction的特化版本,它接受两个相同类型的参数,并返回相同类型的结果。
import java.util.function.BinaryOperator;
//Consumer<T> - 接受一个参数,执行操作但不返回任何结果(通常用于副作用,如打印)。
import java.util.function.Consumer;

public class Lamda {
    public static void main(String[] args) {
//        用匿名内部类写
        Runnable printHello = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello Lambda1!");
            }
        };
        printHello.run();

        // 方式一:直接调用一个无参的Lambda表达式
        Runnable printHello1 = () -> System.out.println("1:Hello Lambda1!");
        printHello1.run();

        //  方式二:定义一个有参的Lambda表达式,并将其赋值给一个变量
        Consumer<String> printMessage = (String message) -> System.out.println(message);
        // 使用定义好的Lambda表达式打印消息
        String message = "2:Hello Lambda!";
        printMessage.accept(message);

        // 方式三:只有一个参数,省略小括号的Lambda表达式
        Consumer<String> printName = name -> System.out.println(name);
        printName.accept("3:Hello Lambda!");

        // 方式四:有两个以上参数,有返回值的Lambda表达式
        // 使用Integer类型的参数来匹配BinaryOperator<Integer>的期望
        BinaryOperator<Integer> add = (Integer a, Integer b) -> a + b;
        System.out.println("Sum: " + add.apply(5, 10)); //

        // 方式五:Lambda体中只有一条语句,省略return和大括号的Lambda表达式
        BiFunction<String, String, Integer> strBi = (String s1, String s2) -> s1.length() - s2.length();
        System.out.println("Length Difference: " + strBi.apply("Hello", "World"));

//        语法格式六 : Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
        List<String> fruits = Arrays.asList("Banana","Apple",  "Cherry");
        Collections.sort(fruits, (String a, String b) -> a.compareTo(b));
        System.out.println(fruits);
        fruits.sort((a, b) -> b.compareTo(a));
        // 打印排序后的列表
        System.out.println(fruits);
    }
}

Lambda表达式应用

Lambda表达式在Java中有着广泛的应用,特别是在与集合(Collections)和流(Streams)API结合使用时。以下是一些Lambda表达式常见的应用场景:

集合操作:使用forEach、map、filter等方法对集合进行遍历、转换和过滤。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Arrays;
import java.util.function.Consumer;

public class LamdaTwo {
    public static void main(String[] args) {
//      用forEach()方法   遍历集合
    List<String> nameList = Arrays.asList("Alice", "Bob", "Charlie","David");
//    要使用匿名内部类实现Consumer接口
        nameList.forEach(new Consumer<String>() {
            @Override
            public void accept(String name) {
                System.out.println(name);
            }
        });
//        使用Lambda表达式可以更简洁地实现相同的功能:
        nameList.forEach(name-> System.out.println(name));


//      过滤集合  使用 Stream API:通过调用 names.stream() 将列表转换为 Stream。Stream API 允许您以声明性方式处理集合。
        List<String> names = Arrays.asList("Bob","Alice", "David", "Charlie");
//       names.stream() 将 names 列表转换成 Stream。
//       Stream:一个元素序列,这些元素可以是独立来源的,比如数组或集合,也可以是操作产生的
        List<String> filteredNames = names.stream().filter(name -> name.startsWith("C"))
                .collect(Collectors.toList());
        System.out.println(filteredNames);

//        3. 映射集合
//        应用映射操作:通过 map 操作对 Stream 中的每个元素应用一个函数
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
        List<Integer> squaredNumbers = numbers.stream()
                .map(number -> number * number)
                .collect(Collectors.toList());
        System.out.println(squaredNumbers);

    }
}



线程:通过Runnable和Callable接口,Lambda表达式可以简洁地表示线程任务。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Version:1.0
 * @Description: TODO(一句话描述该类的功能)
 * @Date: 2024/8/14 13:15
 * @Author: tao
 */
public class LamdaTHread {

    public void firth1() {
//      匿名内部类:
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Hello from a thread!");
                }
            }).start();

        new Thread(() -> {
            System.out.println("Hello from a thread!");
        }).start();

    }

    public void secondth2() {
        // 创建一个 Runnable 任务
        Runnable task = () -> System.out.println("Task is running.");
        // 创建线程并启动
        new Thread(task).start();

    }


    public void thirdth3() {


        // 这是一个Lambda表达式,定义了异步执行的任务,supplyAsync方法 :返回一个CompletableFuture对象,代表异步操作的结果
        CompletableFuture.supplyAsync(() -> {

            // 任务的结果是字符串 "Result of a computation"
            return "Result of a computation";
        }).thenApply(result -> {
//         将返回的结果转大写
            return result.toUpperCase();
        }).thenAccept(result -> {
            // thenAccept方法正在使用 thenApply 方法的结果进行操作
            // 这里使用方法引用System.out::println,将结果打印到控制台
            System.out.println(result);
        });
    }

    public static void main(String[] args) {
        LamdaTHread lambdaThread = new LamdaTHread();

        // 调用 firth1 方法,它将创建并启动一个新线程
        lambdaThread.firth1();

        // 调用 secondth2 方法,它将创建 Runnable 并启动一个新线程
        lambdaThread.secondth2();

        // 调用 thirdth3 方法,它将使用 CompletableFuture 异步执行任务
        lambdaThread.thirdth3();
    }
}

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池示例类,演示如何使用Lambda表达式和线程池执行多个任务。
 */
public class LambdaThreadPool {

    private static final int POOL_SIZE = 10;/// 线程池的大小
    // 需要执行的任务数量
    private static final int TASK_COUNT = 20;//  // 需要执行的任务数量

    private static AtomicInteger completedTaskCount = new AtomicInteger(0);//使用AtomicInteger线程安全地跟踪已完成的任务数量

    public void fourth4() {
        // 创建固定大小的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(POOL_SIZE);
        // 创建Future数组,用于存储由线程池异步执行的任务的结果
        Future<?>[] futures = new Future<?>[TASK_COUNT];

        for (int i = 0; i < TASK_COUNT; i++) {
            final int taskId = i;
            // 提交任务到线程池,并存储返回的Future对象
            futures[i] = executorService.submit(() -> {
                try {
                    // 打印任务正在运行的信息
                    System.out.println("Task " + taskId + " is running in a thread pool.");
                    // 模拟任务执行时间
                    Thread.sleep(1000);
                    // 任务完成,增加完成计数
                    completedTaskCount.incrementAndGet();
                } catch (InterruptedException e) {
                    // 重新设置中断状态,并打印中断信息
                    Thread.currentThread().interrupt();
                    System.out.println("Task " + taskId + " was interrupted.");
                }
            });
        }

        // 关闭线程池,不再接受新任务
        executorService.shutdown();
        try {
            // 等待已提交的任务执行完成,设置超时时间
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                // 如果超时,则尝试立即关闭线程池
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            // 如果当前线程被中断,则立即关闭线程池并重新设置中断状态
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }

        // 检查所有任务是否完成
        for (Future<?> future : futures) {
            try {
                // 等待任务完成,捕获并处理可能抛出的异常
                future.get();
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 打印所有任务完成的信息
        System.out.println("All tasks completed. Total tasks: " + TASK_COUNT + ", Completed tasks: " + completedTaskCount);
    }

    public static void main(String[] args) {
        // 创建LambdaThreadPool实例并调用fourth4方法
        LambdaThreadPool lambdaThreadPool = new LambdaThreadPool();
        lambdaThreadPool.fourth4();
    }
}

事件监听器:对于只包含单个抽象方法的监听器接口,可以使用Lambda表达式来简化事件处理代码。

函数式接口的其他实现:如Predicate、Consumer、Function等,这些接口在Java 8的流API中大量使用。

Lambda表达式的优势

代码简洁:Lambda表达式使得代码更加简洁、易读。

易于并行:结合Java 8的流API,Lambda表达式可以方便地进行并行计算,提高程序性能。

易于理解:对于熟悉函数式编程的开发者来说,Lambda表达式更加直观、易于理解。

结论

Lambda表达式是Java 8中一个关键特性,它不仅简化了代码,还使得Java编程更加现代化,更接近函数式编程的范式。它在集合操作、并行计算和事件处理等方面提供了强大的支持,是现代Java开发中不可或缺的一部分。

Lambda表达式的引入不仅简化了代码,还使得Java更加贴近于函数式编程的范式。在实际编程中,Lambda表达式可以应用于很多场景,例如在集合框架中实现排序、过滤和映射等操作。此外,Lambda表达式还可以用于函数式编程,特别是在Java Streams API中。

通过深入探讨Lambda表达式的概念、语法、应用场景以及它如何改变我们的编程方式,我们可以更好地理解和应用这一特性,从而提高代码的简洁性和可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值