Java如何检测Entity类嵌套ratings列表内sid字段的重复值
Java端校验实现
单个Entity校验
直接通过流式统计去重后的sid数量和原列表长度对比即可,不需要操作索引:
// 校验单个Entity是否存在sid重复,返回true表示有重复 public boolean hasDuplicateSidInEntity(Entity entity) { List<Rating> ratings = entity.getRatings(); if (ratings == null || ratings.size() <= 1) { return false; } long distinctSidCount = ratings.stream() .map(Rating::getSid) .distinct() .count(); return distinctSidCount < ratings.size(); } // 如果需要获取具体重复的sid值 public List<String> listDuplicateSids(Entity entity) { List<Rating> ratings = entity.getRatings(); if (ratings == null || ratings.isEmpty()) { return Collections.emptyList(); } return ratings.stream() .collect(Collectors.groupingBy(Rating::getSid, Collectors.counting())) .entrySet() .stream() .filter(e -> e.getValue() > 1) .map(Map.Entry::getKey) .collect(Collectors.toList()); }
批量数据校验
不管你手上的数据是List<Entity>还是List<List<Rating>>,都可以直接流式遍历校验:
// 校验List<Entity>中所有实例,返回存在重复sid的实例 public List<Entity> filterInvalidEntities(List<Entity> entityList) { return entityList.stream() .filter(this::hasDuplicateSidInEntity) .collect(Collectors.toList()); } // 校验List<List<Rating>>结构 public boolean hasAnyDuplicate(List<List<Rating>> allRatings) { return allRatings.stream() .anyMatch(ratingList -> ratingList.stream().map(Rating::getSid).distinct().count() < ratingList.size() ); }
你之前遇到的IntStream索引问题不需要处理,不需要通过索引定位元素,直接遍历每个列表即可完成校验。
MongoDB端校验方案
MongoDB默认的单字段唯一索引是全局约束,会限制所有文档的ratings.sid都不能重复,不符合「仅单个文档内部sid不重复」的需求,可选以下两种实现方式:
- 复合唯一索引方案:将文档主键和ratings.sid做复合唯一索引,限制同一个文档内的sid不重复
db.your_collection_name.createIndex( {"_id": 1, "ratings.sid": 1}, {unique: true} )
注意:该方案仅在全量更新文档、或者对ratings数组做原子追加操作时生效,能拦截重复sid写入。
- 文档校验规则方案(MongoDB 5.0+支持):给集合添加内置校验规则,写入时自动检查数组内sid是否有重复
db.runCommand({ collMod: "your_collection_name", validator: { $expr: { $eq: [ {$size: "$ratings.sid"}, {$size: {$setUnion: ["$ratings.sid", []]}} ] } }, validationLevel: "strict", validationAction: "error" })
规则逻辑为对比sid数组长度和去重后sid数组长度,不一致则直接拒绝写入。
内容的提问来源于stack exchange,提问作者diaop
相关产品推荐
相关产品推荐

