java8新特性

Lambda表达式

这是 Java 8 最受关注的特性。它允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

  • 语法:(parameters) -> expression 或 (parameters) -> { statements; }
1
2
3
4
5
6
7
8
9
10
// 旧方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World");
}
}).start();

// Java 8 Lambda 方式
new Thread(() -> System.out.println("Hello World")).start();

函数式接口

Lambda 表达式必须依赖于函数式接口。

  • 定义:一个接口中有且仅有一个抽象方法(但可以有多个默认方法或静态方法)。
  • 注解:@FunctionalInterface(可选,用于编译器检查)。
  • 内置四大核心接口
    • Predicate<T>:断言型(输入 T,返回 boolean)
    • Consumer<T>:消费型(输入 T,无返回)
    • Function<T, R>:函数型(输入 T,返回 R)
    • Supplier<T>:供给型(无输入,返回 T)

方法引用

方法引用是 Lambda 表达式的一种更简洁的写法,当 Lambda 体中只是调用一个已存在的方法时,可以使用。

  • 符号:::
  • 常见形式
    • 对象::实例方法名
    • 类名::静态方法名
    • 类名::实例方法名(比较特殊,如 String::length)
    • 类名::new(构造器引用)

Stream API (流式处理)

这是 Java 8 处理集合(Collection)的利器,它借鉴了数据库查询语言和函数式语言的特点。

  • 特点:Stream 不存储数据,不修改源数据,它是延迟执行的(惰性求值)。
  • 操作步骤
    1. 创建流:list.stream()
    2. 中间操作:filter (过滤)、map (映射/转换)、sorted (排序)、distinct (去重)
    3. 终止操作:collect (转回集合)、forEach (遍历)、count (统计)、reduce (归约)
1
2
3
4
5
List<String> list = Arrays.asList("apple", "banana", "orange");
List<String> result = list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.collect(Collectors.toList());

Optional 类

为了解决令人头疼的 NullPointerException(空指针异常)。

  • 本质Optional<T>是一个包装类,代表一个值存在或不存在。

  • 用法

    1
    2
    3
    Optional<String> opt = Optional.ofNullable(getName());
    // 如果有值则打印,否则执行默认操作
    System.out.println(opt.orElse("Unknown"));

案例方便理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//1 Lambda
//A. 集合排序 (Comparator) 这是最常用的场景之一。
// 以前写法
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a); // 降序
}
});
// Lambda 写法
names.sort((a, b) -> b.compareTo(a));

//条件过滤 (Predicate)
// 使用内置的 Predicate 接口
Predicate<Integer> isAdult = (age) -> age >= 18;

System.out.println(isAdult.test(20)); // true
System.out.println(isAdult.test(15)); // false

//函数转换 (Function)
Function<String, Integer> stringToInt = (s) -> Integer.parseInt(s);
Integer result = stringToInt.apply("123"); // 123
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
//2 方法引用
//A. 静态方法引用 (类名::静态方法)
// Lambda 版
Function<String, Integer> lambda = s -> Integer.parseInt(s);
// 方法引用版
Function<String, Integer> methodRef = Integer::parseInt;

//B. 实例方法引用 (对象::实例方法)
StringBuilder sb = new StringBuilder();
// Lambda
Consumer<String> lambda = s -> sb.append(s);
// 方法引用
Consumer<String> methodRef = sb::append;

//C. 特定类型的方法引用 (类名::实例方法)
// Lambda: s 是参数,调用了它的 length() 方法
Function<String, Integer> lambda = s -> s.length();
// 方法引用
Function<String, Integer> methodRef = String::length;

//D. 构造器引用 (类名::new)
// Lambda
Supplier<List<String>> listLambda = () -> new ArrayList<>();
// 方法引用
Supplier<List<String>> listRef = 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//3. Stream API 示例 (实战模拟)
//Stream 是处理数据的“流水线”。我们先定义一个简单的 User 类:
class User {
String name;
int age;
String city;
// 构造函数、Getter/Setter 略
}
//A. 过滤、映射与合并 (最常用)
//任务:找出所有北京的用户,并获取他们的名字列表。
List<User> users = ... // 假设这里有数据

List<String> beijingUserNames = users.stream()
.filter(u -> "北京".equals(u.getCity())) // 过滤
.map(User::getName) // 提取名字
.collect(Collectors.toList()); // 收集成列表

//B. 统计与计算
//任务:计算所有用户的平均年龄。
double avgAge = users.stream()
.mapToInt(User::getAge) // 转为 IntStream
.average() // 计算平均值
.orElse(0.0); // 如果没数据返回 0.0

//C. 分组 (Grouping By)
//任务:按照城市对用户进行分组。
Map<String, List<User>> usersByCity = users.stream()
.collect(Collectors.groupingBy(User::getCity));

// 输出示例:{ "北京": [user1, user2], "上海": [user3] }

//D. 去重与限制
//任务:获取年龄最大的前 3 个不重复的名字。
List<String> top3Names = users.stream()
.sorted(Comparator.comparingInt(User::getAge).reversed()) // 按年龄降序
.map(User::getName)
.distinct() // 去重
.limit(3) // 只取前3个
.collect(Collectors.toList());

//E. FlatMap (扁平化)
//任务:如果每个用户有一组“标签”(List<String> tags),现在要提取所有用户的去重标签。
List<String> allTags = users.stream()
.flatMap(u -> u.getTags().stream()) // 将多个 List 拍平成一个流
.distinct()
.collect(Collectors.toList());