Java实现数组中连续重复n次数字提取:传统与Stream方式
提取数组中连续重复恰好n次的元素(Java实现)
问题背景
给定数组:
int[] nums = {1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 1, 1, 2, 2, 2};
需求是提取数组中连续重复恰好n次的数字。比如当n=3时,结果应该是1、3、5、2;而连续重复4次的4不符合要求,不能纳入结果。
下面这段尝试的代码存在问题:循环条件i < nums.length - 3会忽略数组最后三个元素,取消这个限制又会触发数组越界:
for(int i = 0; i < nums.length - 3; i++) { if(nums[i] == nums[i + 1] && nums[i + 1] == nums[i + 2] && nums[i + 2] != nums[i + 3]) { System.out.println(nums[i]); continue; } }
解决方案
1. 传统循环实现
核心思路是遍历数组,实时统计当前元素的连续重复次数。当遇到不同元素或者遍历到数组末尾时,检查当前统计的次数是否恰好等于n,符合条件就把该元素加入结果列表。
import java.util.ArrayList; import java.util.List; public class ConsecutiveDuplicateExtractor { public static void main(String[] args) { int[] nums = {1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 1, 1, 2, 2, 2}; int targetCount = 3; List<Integer> result = new ArrayList<>(); if (nums.length == 0) { System.out.println(result); return; } int currentNum = nums[0]; int consecutiveCount = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] == currentNum) { consecutiveCount++; } else { // 切换元素时,检查上一组的连续次数 if (consecutiveCount == targetCount) { result.add(currentNum); } currentNum = nums[i]; consecutiveCount = 1; } } // 处理数组最后一组连续元素 if (consecutiveCount == targetCount) { result.add(currentNum); } System.out.println("符合条件的元素:" + result); // 输出 [1, 3, 5, 2] } }
2. Java 8 Stream实现
这里提供两种Stream写法,第一种是结合遍历统计的直观实现,第二种更偏向函数式风格:
写法一:基于遍历统计的Stream实现
利用IntStream遍历数组,用数组保存当前元素和连续次数(因为lambda表达式中无法修改局部变量,所以用数组作为容器):
import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; public class StreamConsecutiveExtractor { public static void main(String[] args) { int[] nums = {1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 1, 1, 2, 2, 2}; int targetCount = 3; List<Integer> result = new ArrayList<>(); if (nums.length == 0) { System.out.println(result); return; } // current[0] = 当前元素,current[1] = 连续次数 int[] current = {nums[0], 1}; IntStream.range(1, nums.length) .forEach(index -> { if (nums[index] == current[0]) { current[1]++; } else { if (current[1] == targetCount) { result.add(current[0]); } current[0] = nums[index]; current[1] = 1; } }); // 处理最后一组元素 if (current[1] == targetCount) { result.add(current[0]); } System.out.println("符合条件的元素:" + result); // 输出 [1, 3, 5, 2] } }
写法二:函数式分组的Stream实现
通过Stream.iterate生成连续重复元素的分组(每个分组包含元素和连续次数),再过滤出次数符合要求的元素:
import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class FunctionalStreamExtractor { public static void main(String[] args) { int[] nums = {1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 1, 1, 2, 2, 2}; int targetCount = 3; if (nums.length == 0) { System.out.println(List.of()); return; } // 生成连续重复分组:每个分组是 [当前索引, 元素值, 连续次数] Stream<int[]> consecutiveGroups = Stream.iterate( new int[]{0, nums[0], 1}, state -> state[0] < nums.length - 1 ? (nums[state[0] + 1] == state[1] ? new int[]{state[0] + 1, state[1], state[2] + 1} : new int[]{state[0] + 1, nums[state[0] + 1], 1}) : null ).takeWhile(state -> state != null); // 过滤出连续次数等于targetCount的元素 List<Integer> result = consecutiveGroups .filter(group -> group[2] == targetCount) .map(group -> group[1]) .collect(Collectors.toList()); System.out.println("符合条件的元素:" + result); // 输出 [1, 3, 5, 2] } }
内容的提问来源于stack exchange,提问作者barry allen
相关产品推荐
相关产品推荐

