Lambda表达式、Stream API和函数式编程详解
Java 8是Java发展史上的一个重要里程碑,引入了许多革命性的新特性,其中最重要的是Lambda表达式和Stream API。这些新特性不仅简化了代码编写,还引入了函数式编程的概念,让Java开发更加高效和优雅。
简化匿名函数的编写,使代码更加简洁和可读。支持函数式编程风格,减少样板代码。
提供强大的数据处理能力,支持过滤、映射、归约等操作,让集合处理更加优雅。
进一步简化Lambda表达式,直接引用已存在的方法,提高代码复用性。
优雅地处理空值,避免NullPointerException,提供更安全的编程方式。
支持Lambda表达式的接口,提供丰富的内置函数式接口,简化函数式编程。
全新设计的日期时间API,线程安全,API设计更加合理和易用。
Lambda表达式是Java 8最重要的新特性之一,它允许我们将函数作为参数传递,简化了匿名内部类的编写。Lambda表达式的基本语法是:(参数) -> 表达式
或 (参数) -> { 语句块 }
。
// 传统匿名内部类方式
Comparator<String> comparator1 = new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
};
// Lambda表达式方式
Comparator<String> comparator2 = (a, b) -> a.compareTo(b);
// 方法引用方式
Comparator<String> comparator3 = String::compareTo;
// 单参数Lambda表达式
List<String> names = Arrays.asList("张三", "李四", "王五");
names.forEach(name -> System.out.println(name));
// 方法引用简化
names.forEach(System.out::println);
Stream API是Java 8引入的另一个重要特性,它提供了一种声明式的数据处理方式。Stream不是数据结构,而是数据源的视图,支持函数式编程风格的操作。
List<String> words = Arrays.asList("Java", "Python", "JavaScript", "Go", "Rust");
// 过滤、映射、收集
List<String> result = words.stream()
.filter(word -> word.length() > 4) // 过滤长度大于4的单词
.map(String::toUpperCase) // 转换为大写
.sorted() // 排序
.collect(Collectors.toList()); // 收集为List
System.out.println(result); // [JAVASCRIPT, PYTHON]
// 数值计算
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.stream()
.filter(n -> n % 2 == 0) // 过滤偶数
.mapToInt(Integer::intValue) // 转换为IntStream
.sum(); // 求和
System.out.println("偶数和: " + sum); // 偶数和: 30
// 分组操作
Map<Integer, List<String>> groupedByLength = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(groupedByLength);
Optional是Java 8引入的一个容器类,用于表示可能为空的值。它的设计目的是减少NullPointerException的发生,提供更安全和优雅的空值处理方式。
// 创建Optional
Optional<String> optional1 = Optional.of("Hello World");
Optional<String> optional2 = Optional.ofNullable(null);
Optional<String> optional3 = Optional.empty();
// 检查值是否存在
if (optional1.isPresent()) {
System.out.println("值存在: " + optional1.get());
}
// 使用ifPresent避免显式检查
optional1.ifPresent(value -> System.out.println("值: " + value));
// 提供默认值
String result1 = optional2.orElse("默认值");
String result2 = optional2.orElseGet(() -> "通过Supplier提供的默认值");
// 链式操作
Optional<String> result = Optional.of("java programming")
.filter(s -> s.length() > 5)
.map(String::toUpperCase)
.map(s -> "Language: " + s);
result.ifPresent(System.out::println); // Language: JAVA PROGRAMMING
// 实际应用场景
public Optional<User> findUserById(String id) {
// 模拟数据库查询
User user = database.findById(id);
return Optional.ofNullable(user);
}
// 安全的链式调用
String email = findUserById("123")
.map(User::getEmail)
.filter(e -> e.contains("@"))
.orElse("未找到有效邮箱");
以下是一个综合运用Java 8新特性的完整示例,展示了Lambda表达式、Stream API和Optional的实际应用:
import java.util.*;
import java.util.stream.*;
import java.util.function.*;
public class Java8FeaturesDemo {
public static void main(String[] args) {
System.out.println("=== Java 8新特性综合示例 ===");
// 示例数据
List<Person> people = Arrays.asList(
new Person("张三", 25, "北京"),
new Person("李四", 30, "上海"),
new Person("王五", 28, "广州"),
new Person("赵六", 35, "深圳")
);
// Lambda表达式和Stream API综合应用
people.stream()
.filter(person -> person.getAge() > 25) // 过滤年龄大于25的人
.sorted(Comparator.comparing(Person::getAge)) // 按年龄排序
.map(Person::getName) // 提取姓名
.forEach(System.out::println); // 输出结果
// 分组统计
Map<String, Long> cityCount = people.stream()
.collect(Collectors.groupingBy(
Person::getCity,
Collectors.counting()
));
System.out.println("各城市人数统计: " + cityCount);
// Optional使用示例
Optional<Person> oldestPerson = people.stream()
.max(Comparator.comparing(Person::getAge));
oldestPerson.ifPresent(person ->
System.out.println("年龄最大的人: " + person.getName())
);
}
static class Person {
private String name;
private int age;
private String city;
public Person(String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
// Getter方法
public String getName() { return name; }
public int getAge() { return age; }
public String getCity() { return city; }
}
}
函数式接口是只有一个抽象方法的接口,是Lambda表达式的基础。Java 8在java.util.function包中提供了许多内置的函数式接口。
断言型接口,接受一个参数,返回boolean值。常用于过滤操作。
Predicate<String> isEmpty = String::isEmpty;
函数型接口,接受一个参数,返回一个结果。常用于映射操作。
Function<String, Integer> length = String::length;
消费型接口,接受一个参数,无返回值。常用于遍历操作。
Consumer<String> print = System.out::println;
供给型接口,无参数,返回一个结果。常用于延迟计算。
Supplier<Date> now = Date::new;