深入理解 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, "
相关推荐
咩咩啃树皮8 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚8 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白10 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司11 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地12 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415912 小时前
TCP超时重传机制是为了解决什么问题?
java
莫逸风14 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
隔窗听雨眠14 小时前
Spring Boot在云原生时代的编程范式革新研究
spring boot·后端·云原生
z1234567898615 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112315 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python