如何用Stream API将List<LoggerMessageDto>转为Map<String, Set<String>>
使用Stream API实现List到指定Map的转换
你可以通过以下几种Stream API的方式实现需求,不同方式适用于不同的Java版本和场景:
方式一:两次Stream遍历(简洁直观,Java 8+)
这种方式代码清晰易懂,适合数据量不大的场景,虽然会遍历两次List,但可读性优先:
List<LoggerMessageDto> result = getSomeResult(); Map<String, Set<String>> map = Map.of( "types", result.stream() .map(LoggerMessageDto::getType) .collect(Collectors.toSet()), "messages", result.stream() .map(LoggerMessageDto::getMessage) .collect(Collectors.toSet()) );
方式二:使用teeing收集器(单次遍历,Java 12+)
Java 12引入的teeing收集器可以同时执行两个收集操作,只遍历一次List,效率更高,适合大数据量场景:
List<LoggerMessageDto> result = getSomeResult(); Map<String, Set<String>> map = result.stream() .collect(Collectors.teeing( // 收集所有type到Set Collectors.mapping(LoggerMessageDto::getType, Collectors.toSet()), // 收集所有message到Set Collectors.mapping(LoggerMessageDto::getMessage, Collectors.toSet()), // 将两个Set合并为目标Map (typesSet, messagesSet) -> Map.of("types", typesSet, "messages", messagesSet) ));
方式三:自定义收集器(兼容Java 8,单次遍历)
如果你的环境是Java 8(不支持teeing),可以通过自定义收集容器实现单次遍历:
首先定义一个承载两个Set的容器类:
class SetPair { private final Set<String> types = new HashSet<>(); private final Set<String> messages = new HashSet<>(); // 添加单个LoggerMessageDto的字段到对应Set public void accept(LoggerMessageDto dto) { types.add(dto.getType()); messages.add(dto.getMessage()); } // 合并两个SetPair(用于并行流场景) public void combine(SetPair other) { types.addAll(other.types); messages.addAll(other.messages); } }
然后通过Stream收集并转换为Map:
List<LoggerMessageDto> result = getSomeResult(); SetPair pair = result.stream() .collect(SetPair::new, SetPair::accept, SetPair::combine); Map<String, Set<String>> map = Map.of("types", pair.types, "messages", pair.messages);
内容的提问来源于stack exchange,提问作者Aleksey Bakharev
相关产品推荐
相关产品推荐

