如何使用Java Stream API获取所有重复元素的索引
Java Stream获取列表重复元素对应索引实现方案
你原有写法的问题在于:input::indexOf只会返回元素第一次出现的索引作为分组键,且分组后收集的是元素值本身而非索引,因此无法得到预期结果。以下是两类需求的具体实现:
需求1:获取「重复元素-对应所有索引」的Map结构
核心思路是先遍历索引,按元素值分组收集所有索引,再过滤掉仅出现1次的非重复元素即可。
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; // 示例输入 List<Integer> input = new ArrayList<>(Arrays.asList(312, 312, 195, 195, 195, 851, 335, 851, 99)); Map<Integer, List<Integer>> duplicateValueToIndexes = IntStream.range(0, input.size()) .boxed() // 以列表元素为键,对应索引为值分组 .collect(Collectors.groupingBy(input::get, Collectors.toList())) .entrySet() .stream() // 仅保留出现次数≥2的重复元素 .filter(entry -> entry.getValue().size() >= 2) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
运行结果完全匹配预期:{312=[0, 1], 195=[2, 3, 4], 851=[5, 7]}
需求2:获取所有重复元素的索引集合
有两种常见实现方式:
- 基于上述需求1的结果直接扁平化处理,逻辑直观
List<Integer> allDuplicateIndexes = duplicateValueToIndexes.values() .stream() .flatMap(List::stream) .sorted() // 如需保证索引按升序排列可添加该行 .collect(Collectors.toList());
- 不生成中间Map的高效写法:先统计元素出现频次,再遍历索引过滤出重复元素对应的位置,时间复杂度更优
import java.util.function.Function; // 先统计每个元素的出现次数 Map<Integer, Long> valueCount = input.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); List<Integer> allDuplicateIndexes = IntStream.range(0, input.size()) .filter(i -> valueCount.get(input.get(i)) >= 2) .boxed() .collect(Collectors.toList());
两种写法运行结果均为:[0, 1, 2, 3, 4, 5, 7]
内容的提问来源于stack exchange,提问作者Ivan Ivanov
相关产品推荐
相关产品推荐

