如何用Java Streams实现同Log ID下重复Tag的检测逻辑?
使用Java Streams检测同一ID下重复Tag的实现方案
核心思路
要实现「同一ID下同一Tag重复则抛出异常」的逻辑,关键是先将每个Log对象拆分为**(ID, Tag)二元组**,再通过分组统计或重复检测来判断是否存在重复组合。
基础实现(分组统计)
首先定义Log类:
class Log { private String id; private List<String> tags; public Log(String id, List<String> tags) { this.id = id; this.tags = tags; } public String getId() { return id; } public List<String> getTags() { return tags; } }
通过flatMap拆分Log为二元组,再用groupingBy统计每个(ID, Tag)组合的出现次数:
import java.util.List; import java.util.Map; import java.util.AbstractMap.SimpleEntry; import java.util.stream.Collectors; public class LogTagChecker { public static void checkForDuplicateTags(List<Log> logs) { // 拆分Log为(ID, Tag)二元组,分组统计次数 Map<SimpleEntry<String, String>, Long> tagCountById = logs.stream() .flatMap(log -> log.getTags().stream() .map(tag -> new SimpleEntry<>(log.getId(), tag))) .collect(Collectors.groupingBy( entry -> entry, Collectors.counting())); // 检测是否存在次数>1的组合 if (tagCountById.values().stream().anyMatch(count -> count > 1)) { throw new IllegalStateException("存在同一ID下重复的Tag"); } } public static void main(String[] args) { // 测试用例1:应抛出异常(log1的tag1重复) List<Log> duplicateLogs = List.of( new Log("log1", List.of("tag1", "tag2")), new Log("log1", List.of("tag1")) ); checkForDuplicateTags(duplicateLogs); // 测试用例2:正常执行(无重复Tag) List<Log> validLogs = List.of( new Log("log1", List.of("tag1", "tag2")), new Log("log2", List.of("tag1")) ); checkForDuplicateTags(validLogs); } }
简化写法(Java 16+ Record)
用Java 16引入的record替代SimpleEntry,代码更清晰:
// 定义Record作为分组键 record IdTag(String id, String tag) {} // 对应统计逻辑 Map<IdTag, Long> tagCountById = logs.stream() .flatMap(log -> log.getTags().stream() .map(tag -> new IdTag(log.getId(), tag))) .collect(Collectors.groupingBy( idTag -> idTag, Collectors.counting()));
高效优化版(无需全量统计)
如果只需要检测是否存在重复,不需要统计所有次数,可以用Set跟踪已出现的二元组,一旦发现重复立即终止流,减少不必要的计算:
import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.AbstractMap.SimpleEntry; public class LogTagChecker { public static void checkForDuplicateTagsOptimized(List<Log> logs) { Set<SimpleEntry<String, String>> seen = new HashSet<>(); boolean hasDuplicates = logs.stream() .flatMap(log -> log.getTags().stream() .map(tag -> new SimpleEntry<>(log.getId(), tag))) .anyMatch(entry -> !seen.add(entry)); // add返回false说明已存在 if (hasDuplicates) { throw new IllegalStateException("存在同一ID下重复的Tag"); } } }
关键步骤解释
flatMap:将每个Log的List<String> tags展开为多个独立的(ID, Tag)条目,解决了List类型无法直接作为分组键的问题。- 分组键选择:
SimpleEntry或自定义record都重写了equals()和hashCode(),可以作为groupingBy的键来唯一标识「ID+Tag」组合。 - 快速检测:
anyMatch和Set.add()的组合能在找到第一个重复时立即停止遍历,性能优于全量统计。
内容的提问来源于stack exchange,提问作者user24498812
相关产品推荐
相关产品推荐

