本文介绍一种基于 java stream 和 hashset 的高效方案,用于批量处理产品列表:对名称重复的产品拼接 category 名称生成 frontname,对唯一名称产品则直接赋值 name。方法时间复杂度接近 o(n),避免嵌套遍历,兼顾可读性与性能。
在实际业务开发中,我们常需根据字段的“唯一性”对对象进行差异化处理。以 Product 类为例:
@Data
public class Product {
private UUID id;
private String name;
private String categoryName;
private String frontName;
}目标是:
✅ 若某 name 在整个列表中出现多次 → frontName = name + "," + categoryName
✅ 若某 name 仅出现一次 → frontName = name
核心思路:先识别所有重复 name,再统一更新。利用 Set.add() 返回值(false 表示已存在)在单次遍历中收集重复项:
// 第一阶段:提取所有重复的 product name Setseen = new HashSet<>(); Set duplicateNames = productList.stream() .map(Product::getName) .filter(name -> !seen.add(name)) // add() 返回 false → 已存在 → 是重复项 .collect(Collectors.toSet()); // 第二阶段:遍历原列表,按重复性设置 frontName productList.forEach(product -> { if (duplicateNames.contains(product.getName())) { product.setFrontName(product.getName() + "," + product.getCategoryName()); } else { product.setFrontName(product.getName()); } });
? 关键点说明: seen.add(name) 在首次遇到 name 时返回 true,后续重复调用返回 false; filter(...) 保留的是所有 第二次及以后出现 的 name,因此 duplicateNames 准确涵盖所有重复值; 整体仅需两次线性遍历(Stream + forEach),无嵌套循环,性能稳定。
.filter(Objects::nonNull)
SetduplicateNames = Collections.unmodifiableSet( productList.stream() .map(p -> Optional.ofNullable(p.getName()).orElse("")) .filter(name -> !seen.add(name)) .collect(Collectors.toSet()) );
该方案简洁、高效、易维护,是处理“按字段重复性差异化赋值”类需求的典型范式。