【Java】Effective Lambda Expressions in Java(二)

简介: 【Java】Effective Lambda Expressions in Java

【Java】Effective Lambda Expressions in Java(一)https://developer.aliyun.com/article/1395331

Use Lambda expressions to Handle Exceptions 使用 Lambda 表达式处理异常

Lambda expressions can be used to handle checked exceptions in Java. Checked exceptions are a type of exception that must be declared in a method’s signature or handled by the caller. When using Lambda expressions to handle checked exceptions, the Lambda expression is used to define the behavior that should be executed in case of an exception, while still allowing the checked exception to be propagated up to the caller.

Lambda 表达式可用于处理 Java 中的校验异常。校验异常是一种必须在方法签名中声明或由调用者处理的异常类型。使用 Lambda 表达式处理校验异常时,Lambda 表达式用于定义异常情况下应执行的行为,同时仍允许将校验异常传播给调用者。

Here is an example of using Lambda expressions to handle a checked exception when reading a file:

下面是一个使用 Lambda 表达式处理读取文件时已检查异常的示例:


List<String> lines = null;  
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {  
    lines = reader.lines()  
                  .map(line -> {  
                      try {  
                          return process(line);  
                      } catch (IOException e) {  
                          throw new UncheckedIOException(e);  
                      }  
                  })  
                  .collect(Collectors.toList());  
} catch (IOException e) {  
    e.printStackTrace();  
}  
private static String process(String line) throws IOException {  
    // process the line  
}

In this example, we are using a Lambda expression to handle a checked exception when processing each line of a file. The code first creates a BufferedReader object that reads from a file named “file.txt”. The lines from the file are then processed using the map() method of the Stream interface. The map() method takes a Function object as input, which is implemented as a Lambda expression in this case. The Lambda expression calls the process() method to process each line, and catches any IOException that may occur. If an IOException occurs, the Lambda expression throws an UncheckedIOException, which is a runtime exception that wraps the original checked exception.

在本示例中,我们使用 Lambda 表达式来处理处理文件每一行时检查到的异常。代码首先创建了一个 BufferedReader 对象,用于读取名为 "file.txt "的文件。

然后使用 Stream 接口的 map() 方法处理文件中的行。

map() 方法将一个 Function 对象作为输入,在本例中实现为一个 Lambda 表达式。Lambda 表达式调用 process() 方法处理每一行,并捕获可能出现的任何 IOException。

如果出现 IO 异常,Lambda 表达式会抛出一个未检查的 IO 异常,这是一个运行时异常,它封装了原始的已检查异常。

Note that in this example, we are using a Lambda expression with a block of statements enclosed in braces. This is because the process() method throws an IOException, which must be caught or re-thrown by the Lambda expression.

请注意,在这个示例中,我们使用的是一个 Lambda 表达式和一个用大括号括起来的语句块。这是因为 process() 方法会抛出一个_IOException_,而 Lambda 表达式必须捕获或重新抛出这个 IOException

By using Lambda expressions to handle checked exceptions, you can create more concise and readable code, and handle exceptions with greater flexibility and modularity. Lambda expressions provide a powerful and flexible way to handle checked exceptions in Java, and can be used in a wide range of scenarios, such as file I/O, network communication, and database access.

通过使用 Lambda 表达式来处理校验异常,您可以创建更简洁、更易读的代码,并以更大的灵活性和模块化来处理异常。Lambda 表达式为在 Java 中处理检查异常提供了一种强大而灵活的方法,可用于文件 I/O、网络通信和数据库访问等多种场景。

Use Lambda expressions to Handle Null Values 使用 Lambda 表达式处理空值

In Java, NullPointerExceptions (NPEs) can often occur when dealing with null values. Lambda expressions can be used to handle null values in a more concise and expressive way, and to prevent NullPointerExceptions from occurring. Here is an example of using Lambda expressions to handle null values when filtering a list of strings:

在 Java 中,处理空值时经常会出现 NullPointerException(NPE)。可以使用 Lambda 表达式以更简洁、更具表现力的方式处理空值,并防止发生 NullPointerException 异常。下面是一个在过滤字符串列表时使用 Lambda 表达式处理空值的示例:


List<String> list = Arrays.asList("apple", null, "banana", "cherry", null);  
List<String> filteredList = list.stream()  
                                .filter(s -> s != null)  
                                .collect(Collectors.toList());  
System.out.println(filteredList);

In this example, we are using the filter() method of the Stream interface to filter a list of strings. The filter() method takes a Predicate object as input, which is implemented as a Lambda expression in this case. The Lambda expression defines a predicate that tests whether a string is not null.

在本例中,我们使用 Stream 接口的 filter() 方法过滤字符串列表。filter()方法将一个谓词对象作为输入,在本例中是以 Lambda 表达式的形式实现的。Lambda 表达式定义了一个谓词,用于测试字符串是否为空。

Note that in this example, we are using the != operator to test for null values. This is because the null value is not equal to any other value, including null itself.

请注意,在本例中,我们使用 != 操作符来测试空值。这是因为null值不等于任何其他值,包括null值本身。

Use Lambda expressions to perform Parallel Operations 使用 Lambda 表达式执行并行操作

Lambda expressions are anonymous functions in Java that can be used to perform a variety of operations, including parallel operations.

Lambda 表达式是 Java 中的匿名函数(但是细节上和真正的匿名函数不一样),可用于执行各种操作,包括并行操作。

Parallelism refers to the ability to perform multiple operations simultaneously, thereby reducing the amount of time it takes to complete a task. In Java, parallelism can be achieved using the Stream API and lambda expressions.

并行性是指同时执行多个操作的能力,从而减少完成任务所需的时间。在 Java 中,可以使用流 API 和 lambda 表达式来实现并行性

The Stream API provides a parallelStream() method that allows you to create parallel streams. Streams are collections of objects that can be processed sequentially or in parallel. By default, streams are processed sequentially, but you can use the parallelStream() method to process them in parallel.

流 API 提供了一个 parallelStream() 方法,允许您创建并行流。

流是可以按顺序或并行处理的对象集合。默认情况下,流是按顺序处理的,但您可以使用 parallelStream() 方法并行处理它们。

To use lambda expressions to perform parallel operations, you first need to create a stream using the parallelStream() method. You can then use lambda expressions to define the operations that are performed on the elements of the stream. The Stream API will automatically split the stream into multiple substreams and distribute them across multiple threads, allowing the operations to be performed in parallel.

要使用 lambda 表达式执行并行操作,首先需要使用 parallelStream() 方法创建一个流。然后,就可以使用 lambda 表达式定义对流元素执行的操作。 **流 API 会自动将流拆分成多个子流,并将它们分配给多个线程,从而允许并行执行操作。

Here’s an example of using lambda expressions to perform a parallel operation:

下面是一个使用 lambda 表达式执行并行操作的示例:


List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
int sum = numbers.parallelStream()  
                .filter(n -> n % 2 == 0)  
                .mapToInt(n -> n)  
                .sum();

Use Lambda expressions to create Custom Collectors  使用 Lambda 表达式创建自定义收集器

A collector is an operation that can be performed on a stream to accumulate the elements of the stream into a final result. Collectors are used with the collect() method of the Stream interface.

收集器是一种可在流上执行的操作,用于将流的元素累加为最终结果。收集器与流接口的 collect() 方法一起使用。

Java provides a number of built-in collectors that perform common operations like grouping elements, counting elements, and calculating averages. However, you can also create your own custom collectors using lambda expressions.

Java 提供了许多内置收集器,可执行分组元素、计数元素和计算平均值等常见操作。 不过,您也可以使用 lambda 表达式创建自己的自定义收集器。

To create a custom collector using lambda expressions, you need to define a new class that implements the Collector interface. The Collector interface has four methods that you need to implement:

要使用 lambda 表达式创建自定义收集器,需要定义一个实现 Collector 接口的新类。收集器接口有四个方法需要实现:

  • The supplier() method returns a function that creates a new mutable result container.
  • The accumulator() method returns a function that adds an element to the result container.
  • The combiner() method returns a function that combines two result containers.
  • The finisher() method returns a function that performs a final transformation on the result container.
  • supplier(): 方法返回一个函数,用于创建一个新的可变结果容器。
  • Accumulator():  方法返回一个将元素添加到结果容器的函数。
  • combiner():方法返回一个将两个结果容器组合在一起的函数。
  • finisher(): 方法返回一个对结果容器执行最终转换的函数。

Here’s an example of creating a custom collector that calculates the average of a stream of integers:

下面是一个创建自定义收集器的示例,用于计算整数流的平均值:


public class AverageCollector implements Collector<Integer, int[], Double> {  
    @Override  
    public Supplier<int[]> supplier() {  
        return () -> new int[2];  
    }  
    @Override  
    public BiConsumer<int[], Integer> accumulator() {  
        return (acc, val) -> {  
            acc[0] += val;  
            acc[1]++;  
        };  
    }  
    @Override  
    public BinaryOperator<int[]> combiner() {  
        return (acc1, acc2) -> {  
            acc1[0] += acc2[0];  
            acc1[1] += acc2[1];  
            return acc1;  
        };  
    }  
    @Override  
    public Function<int[], Double> finisher() {  
        return acc -> ((double) acc[0]) / acc[1];  
    }  
    @Override  
    public Set<Characteristics> characteristics() {  
        return Collections.emptySet();  
    }  
}

In this example, we define a new class called AverageCollector that implements the Collector interface. The supplier() method returns a function that creates a new integer array with two elements to store the sum and count of the elements in the stream.

在本例中,我们定义了一个名为 AverageCollector 的新类,该类实现了收集器接口。supplier() 方法返回一个函数,用于创建一个包含两个元素的新整数数组,用于存储数据流中元素的总和与计数。

The accumulator() method returns a function that adds each element to the sum and increments the count. The combiner() method returns a function that combines two integer arrays by adding their corresponding elements. The finisher() method returns a function that calculates the average by dividing the sum by the count. Finally, the characteristics() method returns an empty set because this collector does not have any special characteristics.

累加器()方法返回一个将每个元素加到总和中并递增计数的函数。combiner() 方法返回一个函数,该函数通过将两个整数数组中的相应元素相加来合并两个数组。finisher() 方法返回一个函数,通过用总和除以计数来计算平均值。最后,characteristics() 方法返回空集,因为该收集器没有任何特殊特征。

Once you’ve defined your custom collector, you can use it with the collect() method of the Stream interface like this:

一旦定义了自定义收集器,就可以像这样将其与 Stream 接口的 collect() 方法结合使用:


List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);


double average = numbers.stream()  
                        .collect(new AverageCollector());

In this example, we create a stream of integers and use the collect() method with our custom AverageCollector to calculate the average of the integers in the stream. The lambda expressions we defined in the AverageCollector class are used to perform the accumulation and transformation operations.

在本例中,我们创建了一个整数流,并使用带有自定义 AverageCollector 的 collect() 方法计算流中整数的平均值。我们在 AverageCollector 类中定义的 lambda 表达式用于执行累加和转换操作。

Use Lambda expressions to create Higher-order Functions 使用 Lambda 表达式创建高阶函数

A higher-order function is a function that takes one or more functions as arguments and/or returns a function as its result. Lambda expressions can be used to create functions that take other functions as arguments or return functions as results.

高阶函数是将一个或多个函数作为参数和/或将一个函数作为结果返回的函数。Lambda 表达式可用于创建将其他函数作为参数或将函数作为结果返回的函数。

To create a higher-order function using lambda expressions, you can define a method that takes a functional interface as a parameter or return value. A functional interface is an interface that has exactly one abstract method and is annotated with the @FunctionalInterface annotation.

要使用 lambda 表达式创建高阶函数,可以定义一个将功能接口作为参数或返回值的方法。功能接口是一个拥有一个抽象方法并使用 @FunctionalInterface 注解的接口。

Here’s an example of creating a higher-order function that takes a function as an argument:

下面是一个创建以函数为参数的高阶函数的示例:


@FunctionalInterface  
interface BinaryOperator<T> {  
    T apply(T t1, T t2);  
}  
public static <T> BinaryOperator<T> compose(BinaryOperator<T> op1, BinaryOperator<T> op2) {  
    return (x, y) -> op1.apply(op2.apply(x, y), y);  
}

In this example, we define a functional interface called BinaryOperator that has an apply() method that takes two arguments and returns a result. We then define a static method called compose() that takes two BinaryOperator functions as arguments and returns a new BinaryOperator function that composes the two input functions.

在本例中,我们定义了一个名为 BinaryOperator 的函数接口,它有一个 apply() 方法,该方法接收两个参数并返回一个结果。然后,我们定义了一个名为 compose() 的静态方法,该方法接收两个 BinaryOperator 函数作为参数,并返回一个新的 BinaryOperator 函数,该函数将两个输入函数合成。

The compose() method takes two BinaryOperator functions as arguments, op1 and op2. It then returns a new BinaryOperator function that applies op1 to the result of applying op2 to its arguments. The lambda expression (x, y) -> op1.apply(op2.apply(x, y), y) defines the new BinaryOperator function. The first argument of the lambda expression (x) is the result of applying op2 to the original arguments, and the second argument (y) is the second original argument.

compose() 方法将 op1 和 op2 这两个二进制操作符函数作为参数。然后,它返回一个新的二进制操作符函数,该函数将 op1 应用于将 op2 应用于其参数的结果。lambda 表达式 (x, y) -> op1.apply(op2.apply(x, y), y) 定义了新的二元运算符函数。lambda 表达式的第一个参数 (x) 是将 op2 应用于原始参数的结果,第二个参数 (y) 是第二个原始参数。

Here’s an example of using the compose() method to compose two BinaryOperator functions:

下面是一个使用 compose() 方法组合两个 BinaryOperator 函数的示例:


BinaryOperator<Integer> add = (x, y) -> x + y;  
BinaryOperator<Integer> multiply = (x, y) -> x * y;  
BinaryOperator<Integer> composed = compose(add, multiply);  
System.out.println(composed.apply(2, 3)); // Output: 8

In this example, we define two BinaryOperator functions: add, which adds its two arguments, and multiply, which multiplies its two arguments. We then use the compose() method to create a new BinaryOperator function that first multiplies its arguments and then adds the result. We test the composed function by applying it to the values 2 and 3, which should result in 8.

在本例中,我们定义了两个 BinaryOperator 函数:add 和 multiply,前者用于将两个参数相加,后者用于将两个参数相乘。然后,我们使用 compose() 方法创建一个新的 BinaryOperator 函数,首先乘以参数,然后将结果相加。我们对组成的函数进行测试,将其应用于数值 2 和 3,结果应为 8。

Lambda expressions can also be used to create higher-order functions that return functions as results. Here’s an example of creating a higher-order function that returns a UnaryOperator function:

Lambda 表达式还可用于创建高阶函数,将函数作为结果返回。下面是创建返回 UnaryOperator 函数的高阶函数的示例:


@FunctionalInterface  
interface UnaryOperator<T> {  
    T apply(T t);  
}  
public static <T> UnaryOperator<T> addValue(T value) {  
    return x -> x + value;  
}

In this example, we define a functional interface called UnaryOperator that has an apply() method that takes one argument and returns a result. We then define a static method called addValue() that takes a value of type T and returns a new UnaryOperator function that adds the value to its argument.

在本例中,我们定义了一个名为 UnaryOperator 的函数接口,它有一个 apply() 方法,该方法接收一个参数并返回一个结果。然后,我们定义了一个名为 addValue() 的静态方法,该方法接收一个 T 类型的值,并返回一个新的 UnaryOperator 函数,将值添加到其参数中。

The addValue() method returns a lambda expression that defines the new UnaryOperator function. The lambda expression x -> x + value takes one argument (x) and adds the value to it.

addValue() 方法返回一个 lambda 表达式,该表达式定义了新的 UnaryOperator 函数。lambda 表达式 x -> x + value 接收一个参数(x)并将值添加到参数中。

Here’s an example of using the addValue() method to create a new UnaryOperator function:

下面是一个使用 addValue() 方法创建新的 UnaryOperator 函数的示例:


UnaryOperator<Integer> add5 = addValue(5);  
System.out.println(add5.apply(2)); // Output: 7

In this example, we use the addValue() method to create a new UnaryOperator function that adds 5 to its argument. We assign the result to the add5 variable, which is now a function that adds 5 to its argument. We test the add5 function by applying it to the value 2, which should result in 7.

在本例中,我们使用 addValue() 方法创建了一个新的 UnaryOperator 函数,将 5 添加到参数中。我们将结果赋值给 add5 变量,它现在是一个将 5 添入其参数的函数。我们对 add5 函数进行测试,将其应用于数值 2,结果应为 7。

Use Lambda expressions to create Closures 使用 Lambda 表达式创建闭包

A closure is a function that can access and modify variables in its enclosing scope. In other words, a closure “closes over” the variables in its enclosing scope and can use them as if they were local variables.

闭包是一个可以访问和修改其外层作用域中变量的函数。换句话说,闭包 "关闭 "其外层作用域中的变量,并能像使用局部变量一样使用它们。

To create a closure using lambda expressions, you can define a lambda expression that references a variable in its enclosing scope. The lambda expression will then capture the value of the variable at the time the lambda expression is created and use that value whenever it is called.

要使用 lambda 表达式创建闭包,可以定义一个 lambda 表达式,在其外层作用域中引用一个变量。然后,在创建 lambda 表达式时,lambda 表达式将捕获变量的值,并在调用时使用该值。

Here’s an example of creating a closure using a lambda expression:

下面是一个使用 lambda 表达式创建闭包的示例:


public class ClosureExample {  
    public static void main(String[] args) {  
        int x = 5;  
        Runnable runnable = () -> System.out.println(x);  
        x = 10;  
        runnable.run(); // Output: 10  
    }  
}

In this example, we define a variable x with the value 5. We then define a lambda expression that references x and prints its value. Finally, we change the value of x to 10 and call the lambda expression.

在本例中,我们定义了一个值为 5 的变量 x。然后,我们定义一个 lambda 表达式,引用 x 并打印其值。最后,我们将 x 的值改为 10 并调用 lambda 表达式。

When the lambda expression is created, it captures the value of x, which is 5 at the time. When we call the lambda expression, it prints the value of x, which is now 10 because we changed its value after the lambda expression was created. The lambda expression “closes over” the variable x and uses it as if it were a local variable.

创建 lambda 表达式时,它会捕捉 x 的值,当时的值是 5。当我们调用 lambda 表达式时,它会打印出 x 的值,现在是 10,因为我们在创建 lambda 表达式后更改了它的值。lambda 表达式 "关闭 "了变量 x,并像使用局部变量一样使用它。

Here’s another example of creating a closure using a lambda expression:

下面是另一个使用lambda表达式创建闭包的示例:


public class ClosureExample {  
    public static void main(String[] args) {  
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);  
        int sum = 0;  
        numbers.forEach(n -> sum += n);  
        System.out.println(sum); // Output: 15  
    }  
}

In this example, we define a list of integers and a variable sum with the initial value 0. We then use a lambda expression to iterate over the list and add each element to the sum variable. Finally, we print the value of sum.

在本例中,我们定义了一个整数列表和一个初始值为 0 的变量 sum。然后,我们使用 lambda 表达式遍历列表,并将每个元素添加到 sum 变量中。最后,我们打印 sum 的值。

The lambda expression “closes over” the variable sum and updates its value each time it is called. This allows us to calculate the sum of the list using a single lambda expression and a single variable, without the need for a separate loop or accumulator.

lambda 表达式 "关闭 "变量 sum,并在每次调用时更新其值。这样,我们就可以使用单个 lambda 表达式和单个变量计算列表的总和,而无需单独的循环或累加器。

Use Lambda expressions with Method References 在方法引用中使用 Lambda 表达式

Method references allow you to refer to an existing method by name instead of defining a new lambda expression. This can make code more concise and readable, especially when working with simple functions.

方法引用允许你通过通过引用一个现有方法,而不是重新定一个新的函数表达式。这会使得代码更加简洁并且可读,特别是在处理简单函数时。

There are four types of method references in Java:

  1. Reference to a static method
  2. Reference to an instance method of a particular object
  3. Reference to an instance method of an arbitrary object of a particular type
  4. Reference to a constructor

Java中有四种方法引用类型:

  1. 静态方法引用
  2. 对特定对象的实例方法的引用
  3. 对特定类型的任意对象的实例方法的引用
  4. 对构造函数的引用

To use a method reference, you can replace the lambda expression with a reference to the method by name. The method reference syntax is similar to the lambda expression syntax, but with the method name and class name instead of the parameter list and arrow.

使用方法引用,你可以使用引用的方法名称替换Lambda表达式,方法引用的语法与 lambda 表达式的语法类似,只是用方法名和类名代替了参数列表和箭头。

Here’s an example of using a method reference to a static method:

下面是使用静态方法引用的例子:


public class MethodReferenceExample {  
    public static void main(String[] args) {  
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);  
        numbers.forEach(System.out::println);  
    }  
}

In this example, we define a list of integers and use the forEach() method to print each element to the console. Instead of using a lambda expression to define the action, we use a method reference to the static method System.out.println(). The double colon (::) operator is used to indicate that we want to reference a method instead of defining a new lambda expression.

这个例子中,我们定义一个整型列表,使用forEach()方法打印到控制台,这里不需要使用Lambda表达式,而是直接使用静态方法System.out.println()的方法引用,双冒号(::)操作符用于表示我们要引用一个方法,而不是定义一个新的 lambda 表达式

Here’s an example of using a method reference to an instance method of a particular object:

下面是一个使用方法引用到特定对象的实例方法的示例:


public class MethodReferenceExample {  
    public static void main(String[] args) {  
        List<String> strings = Arrays.asList("apple", "banana", "cherry");  
        strings.sort(String::compareToIgnoreCase);  
        System.out.println(strings); // Output: [apple, banana, cherry]  
    }  
}

In this example, we define a list of strings and use the sort() method to sort the list in a case-insensitive manner. Instead of using a lambda expression to define the comparator function, we use a method reference to the compareToIgnoreCase() method of the String class.

在这个案例中,我们定义字符串列表并且用 sort() 方法以不区分大小写的方式对列表进行排序,我们没有使用 lambda 表达式来定义比较器函数,而是使用了对 String 类的 compareToIgnoreCase() 方法的引用。

Here’s an example of using a method reference to an instance method of an arbitrary object of a particular type:

下面是一个示例,说明如何使用方法引用来引用特定类型的任意对象的实例方法:


public class MethodReferenceExample {  
    public static void main(String[] args) {  
        List<String> strings = Arrays.asList("apple", "banana", "cherry");  
        strings.forEach(String::toUpperCase);  
        System.out.println(strings); // Output: [apple, banana, cherry]  
    }  
}

Here’s an example of using a method reference to a constructor:

下面是一个将方法引用用于构造函数的示例:


public class MethodReferenceExample {  
    public static void main(String[] args) {  
        List<String> strings = Arrays.asList("apple", "banana", "cherry");  
        List<String> copy = strings.stream()  
                                   .map(String::new)  
                                   .collect(Collectors.toList());  
        System.out.println(copy); // Output: [apple, banana, cherry]  
    }  
}

In this example, we define a list of strings and use the stream() method to create a stream of the strings. We then use the map() method to create a new stream of strings, each of which is created using the String constructor that takes a single argument. This constructor is referenced using a method reference to the String class constructor. Finally, we collect the new stream into a list and print the result.

在这个例子中,我们定义包含字符串的列表并且使用stream 方法创建一个String 流,接着我们使用map方法创建一个新的String流,每个字符串都是使用String构造函数新创建的,该构造函数只需要一个参数。构造函数使用String类构造函数的方法引用。最后,我们将新的数据流收集到一个列表中并打印结果。

Use Lambda expressions with default methods in Interfaces 在接口中使用带有默认方法的 Lambda 表达式

Default methods were introduced in Java 8 to allow interfaces to define a default implementation for a method. This allows interfaces to evolve over time without breaking existing implementations.

Default 默认方法是 Java 8 的新特性之一,主要是允许接口定义默认方法并且实现自己的逻辑,这使得接口可以在不破坏现有实现的情况下随着时间的推移而发展。

Lambda expressions can be used with default methods in interfaces by providing an implementation for the default method in the lambda expression. This allows the lambda expression to be used as an implementation of the interface, even if the interface defines a default method.

通过在 lambda 表达式中为缺省方法提供实现,lambda 表达式可以与接口中的缺省方法一起使用。 即使接口定义了缺省方法,也可以将 lambda 表达式用作接口的实现。

Here’s an example of using a lambda expression with a default method in an interface:

下面是一个使用Lambda表达式和使用静态方法接口的例子。


@FunctionalInterface  
interface Calculator {  
    int add(int x, int y);  
    default int subtract(int x, int y) {  
        return add(x, -y);  
    }  
}


public class DefaultMethodExample {  
public static void main(String[] args) {  
    Calculator calculator = (x, y) -> x + y;  
    System.out.println(calculator.add(2, 3)); // Output: 5  
    System.out.println(calculator.subtract(2, 3)); // Output: -1  
}  
    }

In this example, we define a functional interface called Calculator that has an add() method and a default subtract() method. The subtract() method calls the add() method to perform the subtraction.

上面例子中我们定义Calculator 接口和静态方法subtract和接口方法add(),subtract方法内部会调用add()方法实现减法操作。

We then define a lambda expression that implements the add() method of the Calculator interface. We can use this lambda expression as an implementation of the interface, even though the interface defines a default method.

我们接着使用Lambda表达式定义一个实现了Calculator 接口的add()方法的实现类,我们可以使用这个lambda表达式作为接口的实现,尽管接口定义了一个缺省方法

Use Lambda expressions with the Optional Class 与可选类一起使用 Lambda 表达式

The Optional class was introduced in Java 8 to help prevent null pointer exceptions by providing a container object that may or may not contain a value. Optional provides a set of methods for working with potentially null values in a safer and more concise way.

Optional 是Java8 当中引入的类,它提供一个可能包含或者不包含值的容器预防控制针异常,Optional提供了一组方法,用于以更安全、更简洁的方式处理潜在的空值。

Lambda expressions can be used with the Optional class to define custom behavior for cases where a value is present or absent. Optional provides several methods for working with values, including map(), flatMap(), filter(), ifPresent(), and orElse(). These methods can be used with lambda expressions to define custom behavior for these cases.

Lambda 是可以和 Optional 类一起使用,在值存在或不存在的情况下定义自定义行为,比如map(), flatMap(), filter(), ifPresent(), and orElse() 等方法,可以和 Lambda一起使用

Here’s an example of using a lambda expression with the map() method of the Optional class:

下面是使用Optional.map() 方法的简单案例。


Optional<String> optional = Optional.of("hello");  
Optional<Integer> result = optional.map(s -> s.length());  
System.out.println(result.get()); // Output: 5

In this example, we create an Optional object that contains the string “hello”. We then use the map() method to apply a lambda expression that returns the length of the string. The result of the map() method is an Optional object that contains the result of the lambda expression. We can then use the get() method to retrieve the value from the Optional object and print it to the console.

例子中创建一个内容为“hello”的Optional对象,接着使用 map() 函数应用一个返回字符串长度的lambda表达式。map() 结果是包含Lambda表达式结果的可选对象,我们使用get() 方法从 Optional 对象中获取值。

Here’s an example of using a lambda expression with the filter() method of the Optional class:

下面是使用Optional.filter()的另一个案例


Optional<String> optional = Optional.of("hello");  
Optional<String> result = optional.filter(s -> s.length() > 5);  
System.out.println(result.isPresent()); // Output: false

In this example, we create an Optional object that contains the string “hello”. We then use the filter() method to apply a lambda expression that filters out strings with length less than or equal to 5. Since “hello” has a length of 5, it does not pass the filter and the resulting Optional object is empty. We can then use the isPresent() method to check whether the Optional object contains a value and print the result to the console.

例子中创建一个内容为“hello”的Optional对象,接着使用 filter() 函数应用一个过滤掉字符串长度小于等于5的值lambda表达式,这时候得到的Optional 对象是为空的,使用 isPresent 方法便可以检查是否包含一个值,最终打印结果到控制台。

Here’s an example of using a lambda expression with the orElse() method of the Optional class:

最后是一个orElse()的栗子。


Optional<String> optional = Optional.empty();  
String result = optional.orElseGet(() -> "default");  
System.out.println(result); // Output: default

In this example, we create an empty Optional object and use the orElseGet() method to provide a default value if the Optional object is empty. We pass a lambda expression that returns the default value “default”. Since the Optional object is empty, the orElseGet() method returns the default value, which we then print to the console.

这个例子中我们创建一个空的 Optional 对象并且使用orElseGet()方法在Optional 内部内容为空的的时候提供一个默认值。我们传递一个 lambda 表达式,返回默认值 "default"。由于 Optional 对象为空,orElseGet() 方法返回默认值,然后我们将其打印到控制台。

Thanks for your Attention! Happy Learning!

相关文章
|
25天前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
27天前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
29天前
|
并行计算 Java 编译器
深入理解Java中的Lambda表达式
在Java 8中引入的Lambda表达式,不仅简化了代码编写,还提升了代码可读性。本文将带你探索Lambda表达式背后的逻辑与原理,通过实例展示如何高效利用这一特性优化你的程序。
|
1月前
|
搜索推荐 Java API
探索Java中的Lambda表达式
本文将深入探讨Java 8引入的Lambda表达式,这一特性极大地简化了代码编写,提高了程序的可读性。通过实例分析,我们将了解Lambda表达式的基本概念、使用场景以及如何优雅地重构传统代码。文章不仅适合初学者,也能帮助有经验的开发者加深对Lambda表达式的理解。
|
24天前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
27天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
26 0
|
1月前
|
Java 开发者
探索Java中的Lambda表达式
【10月更文挑战第43天】本文将深入浅出地介绍Java中的Lambda表达式,通过实际代码示例,带领读者理解其背后的原理及应用场景。Lambda表达式不仅简化了代码,还提高了开发效率,是Java开发者必备的技能之一。
|
1天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
3天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
3天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。