JDK 8+新特性(Stream API、Optional、模块化等)
JDK 8+新特性(Stream API、Optional、模块化等)
一、Stream API
1.1 概述
Stream API 是 Java 8 引入的一个新的抽象概念,它允许以声明式的方式处理数据集合。Stream 不是一个数据结构,而是对数据源(如集合、数组等)进行一系列操作的管道。这些操作可以是中间操作(如过滤、映射)和终端操作(如收集、计数)。使用 Stream API 可以使代码更加简洁、易读,并且可以利用多核处理器的并行处理能力。
1.2 基本操作
中间操作
- filter:用于过滤满足条件的元素。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamFilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers);
}
}
- map:用于将元素进行转换。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamMapExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> squaredNumbers = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
System.out.println(squaredNumbers);
}
}
终端操作
- collect:用于将流中的元素收集到一个集合中。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamCollectExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
String result = words.stream()
.collect(Collectors.joining(", "));
System.out.println(result);
}
}
- count:用于统计流中元素的数量。
import java.util.Arrays;
import java.util.List;
public class StreamCountExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream()
.filter(n -> n > 3)
.count();
System.out.println(count);
}
}
1.3 并行流
Stream API 支持并行流,可以利用多核处理器的并行处理能力来提高性能。使用 parallelStream()
方法可以将顺序流转换为并行流。
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long sum = numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
System.out.println(sum);
}
}
二、Optional
2.1 概述
Optional
是 Java 8 引入的一个容器类,用于表示一个值可能存在或不存在的情况。它可以避免空指针异常(NullPointerException
),使代码更加健壮。
2.2 基本用法
- 创建
Optional
对象:Optional.of(T value)
:创建一个包含非空值的Optional
对象。如果传入的值为null
,会抛出NullPointerException
。Optional.ofNullable(T value)
:创建一个可能包含null
值的Optional
对象。如果传入的值为null
,则返回一个空的Optional
对象。Optional.empty()
:创建一个空的Optional
对象。
import java.util.Optional;
public class OptionalCreationExample {
public static void main(String[] args) {
Optional<String> nonEmptyOptional = Optional.of("Hello");
Optional<String> nullableOptional = Optional.ofNullable(null);
Optional<String> emptyOptional = Optional.empty();
}
}
- 判断值是否存在:
isPresent()
:判断Optional
对象中是否包含值。ifPresent(Consumer<? super T> action)
:如果Optional
对象中包含值,则执行指定的操作。
import java.util.Optional;
public class OptionalIsPresentExample {
public static void main(String[] args) {
Optional<String> optional = Optional.of("Hello");
if (optional.isPresent()) {
System.out.println(optional.get());
}
optional.ifPresent(s -> System.out.println(s.toUpperCase()));
}
}
- 获取值:
get()
:如果Optional
对象中包含值,则返回该值;否则抛出NoSuchElementException
。orElse(T other)
:如果Optional
对象中包含值,则返回该值;否则返回指定的默认值。orElseGet(Supplier<? extends T> other)
:如果Optional
对象中包含值,则返回该值;否则通过调用指定的Supplier
函数获取默认值。
import java.util.Optional;
public class OptionalGetValueExample {
public static void main(String[] args) {
Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElse("Default");
System.out.println(value);
String value2 = optional.orElseGet(() -> "Generated Default");
System.out.println(value2);
}
}
三、模块化(Java 9+)
3.1 概述
Java 9 引入了模块化系统(Project Jigsaw),它允许将代码组织成模块,每个模块有自己的声明性依赖和访问控制。模块化可以提高代码的可维护性、安全性和可扩展性,并且可以减少类路径的复杂性。
3.2 模块定义
在 Java 9+ 中,每个模块由一个 module-info.java
文件来定义。该文件位于模块的根目录下,用于声明模块的名称、依赖关系和导出的包。
// module-info.java
module myModule {
// 声明依赖的模块
requires java.base;
requires anotherModule;
// 导出的包
exports com.example.myPackage;
}
3.3 模块的优点
- 封装性:模块可以控制哪些包对外可见,从而提高代码的封装性和安全性。
- 可维护性:模块之间的依赖关系明确,便于代码的维护和升级。
- 性能优化:模块化系统可以减少类加载的开销,提高应用程序的启动性能。
3.4 模块的使用
在编译和运行时,需要指定模块路径和主模块。例如:
# 编译模块
javac --module-path path/to/modules -d out module-info.java com/example/myPackage/MyClass.java
# 运行模块
java --module-path path/to/modules -m myModule/com.example.myPackage.MyClass
四、其他 JDK 8+ 新特性
4.1 接口默认方法和静态方法
Java 8 允许在接口中定义默认方法和静态方法。默认方法使用 default
关键字修饰,为接口提供了默认的实现;静态方法使用 static
关键字修饰,可以直接通过接口名调用。
interface MyInterface {
// 默认方法
default void defaultMethod() {
System.out.println("This is a default method.");
}
// 静态方法
static void staticMethod() {
System.out.println("This is a static method.");
}
}
4.2 日期时间 API
Java 8 引入了新的日期时间 API(java.time
包),它提供了更简洁、线程安全的日期和时间处理方式。例如:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class DateTimeExample {
public static void main(String[] args) {
LocalDate currentDate = LocalDate.now();
LocalTime currentTime = LocalTime.now();
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("Current date: " + currentDate);
System.out.println("Current time: " + currentTime);
System.out.println("Current date and time: " + currentDateTime);
}
}
4.3 方法引用
方法引用是 Lambda 表达式的一种简洁形式,它允许直接引用已有的方法。方法引用使用 ::
符号,常见的方法引用有:
- 静态方法引用:
ClassName::staticMethodName
- 实例方法引用:
instance::instanceMethodName
- 构造方法引用:
ClassName::new
import java.util.Arrays;
import java.util.List;
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry");
words.forEach(System.out::println);
}
}