Java8 Stream API中实现集合list转map的多种方式
作者:codingPower
这篇文章介绍了如何使用Java8的StreamAPI对QuotaDto对象列表进行操作,包括字段提取、映射、组装成Map、枚举类处理、元素拼接、聚合函数以及去重,文章的示例代码讲解详细,感兴趣的小伙伴可以了解下
自定义一个对象:
public class QuotaDto{
private Long id;
private String quotaId;
private String quotaName;
private String reportDate;
private String email;
}
List<QuotaDto> quotaDtolists = new ArrayList<>();
1. 提取对象字段集合
List<String> quotaNames = quotaDtolists.stream()
.map(QuotaDto::getQuotaName)
.filter(Objects::nonNull) // 过滤null值
.collect(Collectors.toList());
优化点:
使用 filter(Objects::nonNull) 避免 null 元素进入列表。
2. List转Map(唯一键)
// 方式1:对象为Value(处理重复键)
Map<String, QuotaDto> quotaMap1 = quotaDtolists.stream()
.collect(Collectors.toMap(
QuotaDto::getQuotaId,
Function.identity(),
(v1, v2) -> v2 // 键冲突时保留新值
));
// 方式2:提取字段为Value
Map<String, String> quotaMap2 = quotaDtolists.stream()
.collect(Collectors.toMap(
QuotaDto::getQuotaId,
QuotaDto::getQuotaName,
(oldVal, newVal) -> newVal
));
关键点:
必须提供合并函数 ((v1, v2) -> ...),否则重复键会抛出 IllegalStateException。
3. 枚举类转Map(修正版)
public enum QuotaEnum {
TYPE_A("A"), TYPE_B("B");
private final String value;
QuotaEnum(String value) { this.value = value; }
public String getValue() { return value; } // 正确方法名
// 枚举转Map
private static final Map<String, QuotaEnum> VALUE_MAP = Arrays.stream(values())
.collect(Collectors.toMap(QuotaEnum::getValue, Function.identity()));
}
修正:
- 方法名
getvalue→getValue(遵循驼峰命名)。 - 使用
Arrays.stream()替代Stream.of()(更直观)。
4. List转Map(类型安全版)
List<Map<String, String>> lists = new ArrayList<>(); // 统一泛型类型
//(v1,v2)->v2 冲突解决函数,当两个不同的map对象具有相同的“userid”键值。保留第二个遇到的值V2
Map<String, String> collect = lists.stream()
.collect(Collectors.toMap(
map -> map.getOrDefault("userid", ""),
map -> map.getOrDefault("orgid", ""),
(v1, v2) -> v2
));
//以某个字段为key
Map<String,List<QuotaDto>> quotaMap= quotaDtolists.stream().collect(Collectors.groupingBy(QuotaDto::getQuotaName));
//list<map> 转 map
Map<String,List<Map<String,String>>> quotaMap= maps.stream().collect(Collectors.groupingBy(map->map.get("userId")));
修正:
- 统一列表中的
Map泛型为<String, String>,避免类型不匹配。 - 使用
getOrDefault防止null值导致的NullPointerException。
5. 元素拼接(防Null版)
String emailAddress = quotaDtolists.stream()
.map(quota -> Optional.ofNullable(quota.getEmail())
.map(email -> email.toUpperCase() + "@qq.com")
.orElse("")) // 处理null或空邮件
.filter(str -> !str.isEmpty())
.collect(Collectors.joining(";"));
//简单版
String emailAddress=quotaDtolists.stream().map(Quota-Quota.getEmail().toUpperCase()+"@qq.com").collect(Collectors.joining(";"));
优化:
使用 Optional 安全处理 null,并过滤空字符串。
6. 聚合操作(安全版)
List<Integer> list = Arrays.asList(1, 2, 3);
// 最大值(避免NoSuchElementException)
Integer maxValue = list.stream()
.max(Integer::compare)
.orElse(0); // 默认值
Integer maxValue2 = list.stream().collect(Collectors.collectingAndThen(Collectors.maxBy((a, b) -> a - b), Optional::get));
// 最小值
Integer minValue = list.stream()
.min(Integer::compare)
.orElse(0);
Integer minValue2 = list.stream().collect(Collectors.collectingAndThen(Collectors.minBy((a, b) -> a - b), Optional::get));
// 求和(直接使用sum()更高效)
int sumValue = list.stream().mapToInt(Integer::intValue).sum();
Integer sumValue2 = list.stream().collect(Collectors.summingInt(item -> item));
// 平均值
Double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0);
Double avg2 = list.stream().collect(Collectors.averagingDouble(x -> x));
// 求汇总数
long count= quotaDtolists.stream().filter(Quota-> Quota.getId()>1).collect(Collectors.counting());
优化:
- 直接使用
max()、min()、sum()等终端操作,代码更简洁。 - 避免使用复杂的
collectingAndThen,除非需要额外处理。
7. 多字段去重(可靠版)
ArrayList<QuotaDto> uniqueList = quotaDtolists.stream()
.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(QuotaDto::getId)
.thenComparing(QuotaDto::getQuotaName)
)),
ArrayList::new
));
//方法二
ArrayList<QuotaDto> collect = quotaDtolists.stream().collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(q -> q.getId()+";"+q.getQuotaName()))), ArrayList::new));
修正:
使用 thenComparing 组合多个字段的比较,避免字符串拼接可能导致的键冲突。
最佳实践总结
- 空值处理:始终考虑字段可能为
null的情况,使用filter或Optional防御。 - 类型安全:统一集合的泛型类型,避免
ClassCastException。 - 键冲突处理:在
toMap中始终提供合并函数,明确冲突解决策略。 - 避免魔法字符串:如
map.get("userid")可替换为常量,提高可维护性。 - 优先内置方法:如
sum()、average()比Collectors.summingInt更简洁。 - 使用组合比较器:多字段去重时,避免拼接字符串,采用
thenComparing。
通过遵循这些原则,可以大幅提升代码的健壮性和可读性。
到此这篇关于Java8 Stream API中实现集合list转map的多种方式的文章就介绍到这了,更多相关Java Stream list转map内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
