使用Java Streams修改匹配对象:为同名Person添加唯一后缀
解决方案
基本要求实现
代码实现
import java.util.AbstractMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; public class PersonStreamProcessor { public static void main(String[] args) { Stream<Person> personStream = Stream.of( new Person("Jeff Bezos", 12), new Person("Jeff Bezos", 165_345_678_910L), new Person("Jeff Bezos", 1_234), new Person("Jeff Bezos(1)", 1_234), new Person("Jeff Bezos(1)(2)", 42), new Person("Bill Gates", 130_000_000_000L) ); Map<String, Double> result = personStream // 按原始名称分组 .collect(Collectors.groupingBy( Person::getName, // 对每组生成唯一名称映射 Collectors.collectingAndThen( Collectors.toList(), list -> { AtomicInteger counter = new AtomicInteger(0); return list.stream() .map(p -> new AbstractMap.SimpleEntry<>( // 第一个元素保留原名,后续添加带计数器的后缀 counter.incrementAndGet() == 1 ? p.name : p.name + "(" + counter.get() + ")", p.netWorth )) .collect(Collectors.toMap( AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue )); } ) )) // 合并所有分组结果 .values() .stream() .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); // 输出结果 result.forEach((k, v) -> System.out.printf("%s: %.0f%n", k, v)); } } class Person { public String name; public double netWorth; public Person(String name, double netWorth) { this.name = name; this.netWorth = netWorth; } }
思路说明
- 用
Collectors.groupingBy按Person的原始名称分组,将同名元素归为一组; - 对每组通过
Collectors.collectingAndThen处理:先转成列表,再用AtomicInteger做计数器生成唯一名称,组内第一个元素保留原名,后续元素添加(计数器值)后缀; - 最后合并所有分组的结果为一个全局Map,保证所有键唯一。
进阶要求实现(按净资产优先级分配名称)
代码实现
import java.util.AbstractMap; import java.util.Comparator; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; public class PersonStreamProcessor { public static void main(String[] args) { Stream<Person> personStream = Stream.of( new Person("Jeff Bezos", 12), new Person("Jeff Bezos", 165_345_678_910L), new Person("Jeff Bezos", 1_234), new Person("Jeff Bezos(1)", 1_234), new Person("Jeff Bezos(1)(2)", 42), new Person("Bill Gates", 130_000_000_000L) ); Map<String, Double> result = personStream .collect(Collectors.groupingBy( Person::getName, Collectors.collectingAndThen( Collectors.toList(), list -> list.stream() // 按净资产降序排序,高资产元素优先获得简洁名称 .sorted(Comparator.comparingDouble(Person::getNetWorth).reversed()) .map(p -> { AtomicInteger counter = new AtomicInteger(0); return new AbstractMap.SimpleEntry<>( counter.incrementAndGet() == 1 ? p.name : p.name + "(" + counter.get() + ")", p.netWorth ); }) .collect(Collectors.toMap( AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue )) } ) )) .values() .stream() .flatMap(map -> map.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); result.forEach((k, v) -> System.out.printf("%s: %.0f%n", k, v)); } } class Person { public String name; public double netWorth; public Person(String name, double netWorth) { this.name = name; this.netWorth = netWorth; } public double getNetWorth() { return netWorth; } }
思路说明
在基本要求的逻辑上增加了组内排序步骤:对每组元素按净资产降序排列,让净资产最高的元素优先被处理,保留最简洁的原名,后续元素依次添加后缀,满足“高资产用简洁名称”的进阶要求。
内容的提问来源于stack exchange,提问作者Ievgen
相关产品推荐
相关产品推荐

