深入理解 Java 中的 Lambda 表达式与函数式编程

引言

Java 8 引入的 Stream API 是处理集合数据的强大工具,结合 Lambda 表达式,可以极大地简化集合操作。本文将全面介绍 Stream API 的常用操作,涵盖 ​实体类 Map 互转生成新 List取内层嵌套的 Map 组成 List循环过滤根据多个属性过滤分组去重根据条件筛选数据​ 等常见场景。通过学习本文,你将掌握 Stream API 的 95% 常用操作,提升代码的简洁性和效率。


1. 实体类 Map 互转

场景:将 List<实体类> 转换为 Map<Key, 实体类>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 将 List<Person> 转换为 Map<ID, Person>
Map<Integer, Person> personMap = people.stream()
    .collect(Collectors.toMap(Person::getId, Function.identity()));

场景:将 Map<Key, Value> 转换为 List<实体类>

复制代码

java

复制代码
Map<Integer, Person> personMap = Map.of(
    1, new Person(1, "Alice"),
    2, new Person(2, "Bob")
);

// 将 Map<ID, Person> 转换为 List<Person>
List<Person> people = personMap.values().stream()
    .collect(Collectors.toList());

2. 生成新的 List

场景:将 List<实体类> 转换为 List<DTO>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 将 List<Person> 转换为 List<PersonDTO>
List<PersonDTO> personDTOs = people.stream()
    .map(person -> new PersonDTO(person.getId(), person.getName()))
    .collect(Collectors.toList());

3. 取内层嵌套的 Map 组成 List

场景:从 List<Map<String, Object>> 中提取某个字段组成 List

复制代码

java

复制代码
List<Map<String, Object>> data = Arrays.asList(
    Map.of("name", "Alice", "age", 25),
    Map.of("name", "Bob", "age", 30)
);

// 提取 "name" 字段组成 List<String>
List<String> names = data.stream()
    .map(map -> (String) map.get("name"))
    .collect(Collectors.toList());

4. 循环

场景:遍历 List<实体类> 并打印

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 遍历并打印
people.forEach(person -> System.out.println(person.getName()));

5. 过滤

场景:根据条件过滤 List<实体类>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 过滤出名字长度大于 3 的人
List<Person> filteredPeople = people.stream()
    .filter(person -> person.getName().length() > 3)
    .collect(Collectors.toList());

6. 根据多个属性过滤

场景:根据多个条件过滤 List<实体类>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice", 25),
    new Person(2, "Bob", 30),
    new Person(3, "Charlie", 35)
);

// 过滤出年龄大于 30 且名字长度大于 3 的人
List<Person> filteredPeople = people.stream()
    .filter(person -> person.getAge() > 30 && person.getName().length() > 3)
    .collect(Collectors.toList());

7. 分组

场景:根据某个字段分组

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice", 25),
    new Person(2, "Bob", 30),
    new Person(3, "Charlie", 25)
);

// 根据年龄分组
Map<Integer, List<Person>> groupedByAge = people.stream()
    .collect(Collectors.groupingBy(Person::getAge));

8. 去重

场景:根据某个字段去重

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Alice")
);

// 根据名字去重
List<Person> distinctPeople = people.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toMap(Person::getName, Function.identity(), (p1, p2) -> p1),
        map -> new ArrayList<>(map.values())
    ));

9. 根据条件筛选数据

场景:根据条件筛选并返回第一个匹配项

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 查找名字为 "Bob" 的人
Optional<Person> bob = people.stream()
    .filter(person -> person.getName().equals("Bob"))
    .findFirst();

10. 其他常用操作

场景:计算总和

复制代码

java

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 计算总和
int sum = numbers.stream()
    .reduce(0, Integer::sum);

场景:查找最大值

复制代码

java

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 查找最大值
Optional<Integer> max = numbers.stream()
    .max(Integer::compareTo);

场景:排序

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 根据名字排序
List<Person> sortedPeople = people.stream()
    .sorted(Comparator.comparing(Person::getName))
    .collect(Collectors.toList());

场景:扁平化操作(FlatMap)

复制代码

java

复制代码
List<List<String>> nestedList = Arrays.asList(
    Arrays.asList("Alice", "Bob"),
    Arrays.asList("Charlie", "David")
);

// 扁平化为一个 List<String>
List<String> flatList = nestedList.stream()
    .flatMap(List::stream)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 Map<Key, List<实体类>>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice", 25),
    new Person(2, "Bob", 30),
    new Person(3, "Charlie", 25)
);

// 根据年龄分组
Map<Integer, List<Person>> groupedByAge = people.stream()
    .collect(Collectors.groupingBy(Person::getAge));

场景:将 List<实体类> 转换为 Map<Key, Value>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 将 List<Person> 转换为 Map<ID, Name>
Map<Integer, String> idToNameMap = people.stream()
    .collect(Collectors.toMap(Person::getId, Person::getName));

场景:将 List<实体类> 转换为 Set<实体类>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Alice")
);

// 将 List<Person> 转换为 Set<Person>
Set<Person> uniquePeople = new HashSet<>(people);

场景:将 List<实体类> 转换为 List<String>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 将 List<Person> 转换为 List<String>
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<Integer>

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob")
);

// 将 List<Person> 转换为 List<Integer>
List<Integer> ids = people.stream()
    .map(Person::getId)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段排序

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字排序
List<Person> sortedPeople = people.stream()
    .sorted(Comparator.comparing(Person::getName))
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段去重

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Alice")
);

// 将 List<Person> 转换为 List<Person>,并根据名字去重
List<Person> distinctPeople = people.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toMap(Person::getName, Function.identity(), (p1, p2) -> p1),
        map -> new ArrayList<>(map.values())
    ));

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段分组

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice", 25),
    new Person(2, "Bob", 30),
    new Person(3, "Charlie", 25)
);

// 将 List<Person> 转换为 List<Person>,并根据年龄分组
Map<Integer, List<Person>> groupedByAge = people.stream()
    .collect(Collectors.groupingBy(Person::getAge));

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段过滤

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字过滤
List<Person> filteredPeople = people.stream()
    .filter(person -> person.getName().length() > 3)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段映射

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字映射
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "Charlie")
);

// 将 List<Person> 转换为 List<Person>,并根据名字归约
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

场景:将 List<实体类> 转换为 List<实体类>,并根据某个字段归约

复制代码

java

复制代码
List<Person> people = Arrays.asList(
    new Person(1, "Alice"),
    new Person(2, "Bob"),
    new Person(3, "
相关推荐
ruanjiananquan993 分钟前
c,c++语言的栈内存、堆内存及任意读写内存
java·c语言·c++
chuanauc30 分钟前
Kubernets K8s 学习
java·学习·kubernetes
一头生产的驴1 小时前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao1 小时前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc7871 小时前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
YuTaoShao3 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张33 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx6 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野7 小时前
【Java|集合类】list遍历的6种方式
java·python·list
二进制person7 小时前
Java SE--方法的使用
java·开发语言·算法