深入理解 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, "
相关推荐
考虑考虑12 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613512 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊13 小时前
Java学习第22天 - 云原生与容器化
java
渣哥15 小时前
原来 Java 里线程安全集合有这么多种
java
间彧15 小时前
Spring Boot集成Spring Security完整指南
java
间彧15 小时前
Spring Secutiy基本原理及工作流程
java
Java水解16 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆19 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学19 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole19 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端