Java 8 编程技巧:Lambda 表达式、Streams API、默认方法
Java 8 引入了一些关键特性,这些特性包括 Lambda 表达式、Streams API、默认方法。其中,Lambda 表达式使代码更加简洁和易于维护;Streams API 提供了一种高效的数据处理方式;默认方法允许在接口中定义方法的实现,使得接口更加灵活。下面将详细介绍这些特性及其在实际编程中的应用。
一、Lambda 表达式
1、概述
Lambda 表达式是 Java 8 的一个重要特性,它允许我们以一种更加简洁的方式来表示匿名函数。Lambda 表达式的语法非常简洁,通常由参数列表、箭头符号(->)和函数体组成。
2、基础语法
Lambda 表达式的基本语法如下:
(parameters) -> expression
或
(parameters) -> { statements; }
例如,以下是一个简单的 Lambda 表达式,它接受两个整数并返回它们的和:
(int a, int b) -> a + b
3、Lambda 表达式的应用场景
a、集合排序
Lambda 表达式可以用于对集合进行排序。例如,以下代码使用 Lambda 表达式对一个 List
进行排序:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
Collections.sort(names, (a, b) -> a.compareTo(b));
b、线程的创建
我们还可以使用 Lambda 表达式来简化线程的创建:
new Thread(() -> System.out.println("Hello from a thread!")).start();
4、方法引用
方法引用是 Lambda 表达式的一种简洁形式,它使用 ::
符号来引用方法。例如,以下代码使用方法引用来打印集合中的每个元素:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
names.forEach(System.out::println);
二、Streams API
1、概述
Streams API 是 Java 8 中的另一项重要特性,它提供了一种高效的数据处理方式。Streams API 允许我们以声明性风格来处理数据集合,从而简化代码并提高可读性。
2、创建 Stream
我们可以从多个来源创建 Stream,例如集合、数组、文件等。以下是一些常见的创建 Stream 的方法:
a、从集合创建 Stream
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
Stream<String> stream = names.stream();
b、从数组创建 Stream
String[] nameArray = {"Tom", "Jerry", "Mickey", "Donald"};
Stream<String> stream = Arrays.stream(nameArray);
3、中间操作
中间操作用于转换或过滤流中的元素,这些操作是惰性的,只有在终端操作执行时才会实际处理数据。常见的中间操作包括 filter
、map
、sorted
等。
a、过滤
filter
方法用于筛选符合条件的元素:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
names.stream().filter(name -> name.startsWith("T")).forEach(System.out::println);
b、映射
map
方法用于将每个元素转换为另一种形式:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
names.stream().map(String::toUpperCase).forEach(System.out::println);
4、终端操作
终端操作用于触发流的处理,并返回一个结果或副作用。常见的终端操作包括 forEach
、collect
、reduce
等。
a、遍历
forEach
方法用于遍历流中的每个元素:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
names.stream().forEach(System.out::println);
b、收集
collect
方法用于将流中的元素收集到集合中:
List<String> names = Arrays.asList("Tom", "Jerry", "Mickey", "Donald");
List<String> filteredNames = names.stream().filter(name -> name.startsWith("T")).collect(Collectors.toList());
c、归约
reduce
方法用于将流中的元素组合成一个值:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);
三、默认方法
1、概述
默认方法是 Java 8 引入的一种新特性,它允许在接口中定义方法的默认实现。这使得接口更加灵活,同时保持了向后兼容性。
2、定义默认方法
我们可以使用 default
关键字来定义默认方法:
interface MyInterface {
default void defaultMethod() {
System.out.println("This is a default method");
}
}
3、使用默认方法
实现接口的类可以直接使用默认方法:
class MyClass implements MyInterface {
// No need to override the default method
}
public class Main {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.defaultMethod(); // Output: This is a default method
}
}
4、重写默认方法
实现接口的类也可以选择重写默认方法:
class MyClass implements MyInterface {
@Override
public void defaultMethod() {
System.out.println("This is an overridden default method");
}
}
public class Main {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.defaultMethod(); // Output: This is an overridden default method
}
}
四、Optional 类
1、概述
Optional
类是 Java 8 引入的另一个重要特性,它用于解决可能出现的空指针异常。Optional
是一个容器类,它可以包含一个非空值,也可以为空。
2、创建 Optional 对象
我们可以使用 Optional.of
、Optional.ofNullable
和 Optional.empty
方法来创建 Optional
对象:
Optional<String> nonEmptyOptional = Optional.of("Hello");
Optional<String> nullableOptional = Optional.ofNullable(null);
Optional<String> emptyOptional = Optional.empty();
3、使用 Optional 对象
Optional
类提供了一些方法来处理可能为空的值,例如 isPresent
、ifPresent
、orElse
等。
a、检查值是否存在
Optional<String> optional = Optional.of("Hello");
if (optional.isPresent()) {
System.out.println(optional.get());
}
b、执行操作如果值存在
Optional<String> optional = Optional.of("Hello");
optional.ifPresent(System.out::println);
c、提供默认值
Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElse("Default Value");
System.out.println(value); // Output: Default Value
五、函数式接口
1、概述
函数式接口是只包含一个抽象方法的接口。Java 8 提供了一些常用的函数式接口,例如 Predicate
、Function
、Consumer
和 Supplier
。这些接口与 Lambda 表达式结合使用,使得代码更加简洁。
2、常用的函数式接口
a、Predicate 接口
Predicate
接口用于表示一个布尔值函数,它接受一个输入参数并返回一个布尔值:
Predicate<String> isLongerThan5 = s -> s.length() > 5;
System.out.println(isLongerThan5.test("Hello")); // Output: false
b、Function 接口
Function
接口用于表示一个接受一个输入参数并返回一个结果的函数:
Function<String, Integer> stringLength = String::length;
System.out.println(stringLength.apply("Hello")); // Output: 5
c、Consumer 接口
Consumer
接口用于表示一个接受一个输入参数并进行某种操作的函数:
Consumer<String> print = System.out::println;
print.accept("Hello"); // Output: Hello
d、Supplier 接口
Supplier
接口用于表示一个提供结果的函数,不接受任何输入参数:
Supplier<String> supplier = () -> "Hello";
System.out.println(supplier.get()); // Output: Hello
六、日期和时间 API
1、概述
Java 8 引入了全新的日期和时间 API,它位于 java.time
包中。新的日期和时间 API 提供了更好的日期和时间处理能力,并且更易于使用。
2、LocalDate 类
LocalDate
类表示一个日期,格式为 YYYY-MM-DD
。我们可以使用 LocalDate
类来表示和操作日期:
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 1);
3、LocalTime 类
LocalTime
类表示一个时间,格式为 HH-MM-SS
。我们可以使用 LocalTime
类来表示和操作时间:
LocalTime now = LocalTime.now();
LocalTime bedtime = LocalTime.of(22, 30);
4、LocalDateTime 类
LocalDateTime
类表示一个日期和时间的组合,格式为 YYYY-MM-DDTHH-MM-SS
。我们可以使用 LocalDateTime
类来表示和操作日期和时间:
LocalDateTime now = LocalDateTime.now();
LocalDateTime meeting = LocalDateTime.of(2023, Month.OCTOBER, 15, 14, 30);
5、Duration 和 Period 类
Duration
类用于表示时间的持续时间,而 Period
类用于表示日期的间隔:
Duration duration = Duration.ofHours(2);
Period period = Period.ofDays(5);
七、并发增强
1、CompletableFuture 类
CompletableFuture
类是 Java 8 引入的一个新的并发类,它提供了更强大的异步编程能力。我们可以使用 CompletableFuture
类来异步执行任务,并在任务完成后继续执行其他操作。
a、创建 CompletableFuture 对象
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("Hello from a separate thread");
});
b、组合多个 CompletableFuture
我们可以使用 thenApply
、thenAccept
和 thenCombine
等方法来组合多个 CompletableFuture
对象:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Integer> result = future1.thenCombine(future2, Integer::sum);
System.out.println(result.join()); // Output: 30
八、Nashorn JavaScript 引擎
1、概述
Nashorn 是 Java 8 引入的一个新的 JavaScript 引擎,它允许我们在 Java 应用程序中嵌入和执行 JavaScript 代码。
2、执行 JavaScript 代码
我们可以使用 ScriptEngineManager
类来执行 JavaScript 代码:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
try {
engine.eval("print('Hello from JavaScript')");
} catch (ScriptException e) {
e.printStackTrace();
}
3、调用 Java 方法
我们还可以在 JavaScript 代码中调用 Java 方法:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
try {
engine.eval("var result = java.lang.Math.max(10, 20); print(result);");
} catch (ScriptException e) {
e.printStackTrace();
}
通过了解和掌握 Java 8 的这些新特性,我们可以编写出更加简洁、高效和易于维护的代码。希望本文对你深入理解 Java 8 编程技巧有所帮助。
相关问答FAQs:
1. Java8编程有哪些新特性?
Java8引入了许多新特性,包括Lambda表达式、函数式接口、流式编程、默认方法等。这些新特性使得Java8编程更加简洁、灵活和高效。
2. 如何使用Lambda表达式进行Java8编程?
Lambda表达式是Java8引入的一种新的语法结构,可以简洁地表示函数式接口的实现。通过Lambda表达式,可以将一个函数作为参数传递给另一个函数,或者定义一个匿名函数。在Java8编程中,可以使用Lambda表达式来实现函数式编程的思想,提高代码的可读性和可维护性。
3. 如何使用流式编程进行Java8编程?
流式编程是Java8引入的一种新的编程模式,通过流(Stream)来处理集合中的数据。通过使用流式编程,可以简化代码,提高代码的可读性和可维护性。在Java8编程中,可以使用流式编程来进行数据的筛选、转换、排序等操作,实现更加优雅和高效的代码。
原创文章,作者:Edit1,如若转载,请注明出处:https://docs.pingcode.com/baike/357073