引言

Java 8是Java历史上最重要的版本之一。本文全面介绍Java 8的核心新特性。

一、Lambda表达式

1.1 基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 传统写法
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};

// Lambda写法
Runnable r2 = () -> System.out.println("Hello");

// 有参数的Lambda
Comparator<Integer> comp = (a, b) -> a - b;

// 多行Lambda
Comparator<Integer> comp2 = (a, b) -> {
int result = a - b;
return result;
};

1.2 函数式接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@FunctionalInterface
interface MyFunction {
int calculate(int a, int b);
}

// 使用Lambda实现
MyFunction add = (a, b) -> a + b;
System.out.println(add.calculate(5, 3)); // 8

// 内置函数式接口
// Function<T, R>
Function<String, Integer> parser = Integer::parseInt;

// Predicate<T>
Predicate<String> isEmpty = String::isEmpty;

// Consumer<T>
Consumer<String> printer = System.out::println;

// Supplier<T>
Supplier<Double> random = Math::random;

二、Stream API

2.1 创建Stream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 从集合创建
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();

// 从数组创建
int[] arr = {1, 2, 3};
IntStream intStream = Arrays.stream(arr);

// 使用Stream.of
Stream<String> stream2 = Stream.of("a", "b", "c");

// 无限流
Stream<Integer> iterate = Stream.iterate(0, n -> n + 1);
Stream<Double> generate = Stream.generate(Math::random);

2.2 中间操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// filter:过滤
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);

// map:映射转换
numbers.stream()
.map(n -> n * 2)
.forEach(System.out::println);

// flatMap:扁平化
List<List<Integer>> lists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4)
);
lists.stream()
.flatMap(List::stream)
.forEach(System.out::println);

// distinct:去重
Arrays.asList(1, 2, 2, 3, 3, 3)
.stream()
.distinct()
.forEach(System.out::println);

// sorted:排序
numbers.stream()
.sorted()
.forEach(System.out::println);

// limit:限制
numbers.stream()
.limit(5)
.forEach(System.out::println);

// skip:跳过
numbers.stream()
.skip(5)
.forEach(System.out::println);

2.3 终端操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// forEach:遍历
numbers.stream().forEach(System.out::println);

// collect:收集
List<Integer> result = numbers.stream()
.filter(n -> n > 2)
.collect(Collectors.toList());

// count:计数
long count = numbers.stream().count();

// reduce:归约
int sum = numbers.stream().reduce(0, Integer::sum);
int product = numbers.stream().reduce(1, (a, b) -> a * b);

// min/max:最小/最大值
Optional<Integer> min = numbers.stream().min(Integer::compare);
Optional<Integer> max = numbers.stream().max(Integer::compare);

// anyMatch/allMatch/noneMatch:匹配
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
boolean allPositive = numbers.stream().allMatch(n -> n > 0);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);

// findFirst/findAny:查找
Optional<Integer> first = numbers.stream().findFirst();
Optional<Integer> any = numbers.stream().findAny();

2.4 Collectors收集器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
List<String> list = Arrays.asList("apple", "banana", "cherry");

// toList
List<String> result = list.stream().collect(Collectors.toList());

// toSet
Set<String> set = list.stream().collect(Collectors.toSet());

// toMap
Map<String, Integer> map = list.stream()
.collect(Collectors.toMap(s -> s, String::length));

// joining
String joined = list.stream().collect(Collectors.joining(", "));

// groupingBy
Map<Integer, List<String>> grouped = list.stream()
.collect(Collectors.groupingBy(String::length));

// partitioningBy
Map<Boolean, List<String>> partitioned = list.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 5));

// counting
long count = list.stream().collect(Collectors.counting());

// summingInt
int totalLength = list.stream()
.collect(Collectors.summingInt(String::length));

三、Optional类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 创建Optional
Optional<String> optional1 = Optional.of("Hello");
Optional<String> optional2 = Optional.ofNullable(null);
Optional<String> optional3 = Optional.empty();

// isPresent:判断是否有值
if (optional1.isPresent()) {
System.out.println(optional1.get());
}

// ifPresent:如果有值则执行
optional1.ifPresent(System.out::println);

// orElse:提供默认值
String value = optional2.orElse("Default");

// orElseGet:提供默认值(延迟执行)
String value2 = optional2.orElseGet(() -> "Default");

// orElseThrow:抛出异常
String value3 = optional2.orElseThrow(() -> new RuntimeException("No value"));

// map:转换
Optional<Integer> length = optional1.map(String::length);

// flatMap:扁平化映射
Optional<String> upper = optional1.flatMap(s -> Optional.of(s.toUpperCase()));

// filter:过滤
Optional<String> filtered = optional1.filter(s -> s.length() > 3);

四、方法引用

1
2
3
4
5
6
7
8
9
10
11
12
13
// 静态方法引用
Function<String, Integer> parser1 = Integer::parseInt;

// 实例方法引用
String str = "Hello";
Supplier<Integer> supplier = str::length;

// 类方法引用
Function<String, Integer> function = String::length;

// 构造器引用
Supplier<List<String>> listSupplier = ArrayList::new;
Function<Integer, List<String>> listFunction = ArrayList::new;

五、接口默认方法和静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
interface MyInterface {
// 抽象方法
void abstractMethod();

// 默认方法
default void defaultMethod() {
System.out.println("Default method");
}

// 静态方法
static void staticMethod() {
System.out.println("Static method");
}
}

class MyClass implements MyInterface {
@Override
public void abstractMethod() {
System.out.println("Abstract method implementation");
}
}

// 使用
MyClass obj = new MyClass();
obj.abstractMethod();
obj.defaultMethod();
MyInterface.staticMethod();

六、新的日期时间API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// LocalDate
LocalDate date = LocalDate.now();
LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 1);

// LocalTime
LocalTime time = LocalTime.now();
LocalTime lunchTime = LocalTime.of(12, 30);

// LocalDateTime
LocalDateTime datetime = LocalDateTime.now();

// ZonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.now();

// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = datetime.format(formatter);

// 解析
LocalDateTime parsed = LocalDateTime.parse("2022-08-22 13:20:00", formatter);

// 日期运算
LocalDate tomorrow = date.plusDays(1);
LocalDate lastWeek = date.minusWeeks(1);

// 时间间隔
Period period = Period.between(birthday, date);
Duration duration = Duration.between(lunchTime, time);

总结

Java 8核心特性:

  1. Lambda表达式:简化代码
  2. Stream API:函数式数据处理
  3. Optional:避免空指针
  4. 方法引用:更简洁的Lambda
  5. 接口增强:默认方法和静态方法
  6. 新日期API:更好用的日期时间处理

参考资料