Java IntStream实现无限素数流的Codewars问题排查
解决Codewars Prime Streaming题目中多次调用stream()状态残留的问题
你遇到的核心问题是静态ArrayList的全局状态残留——第一次调用stream()时生成的素数会被保留在静态列表中,后续调用stream()时,isPrime()方法会基于这个已填充的列表判断,导致流不再从2开始生成新的素数,而是跳过已存在的素数,直接从上次结束的位置继续,最终测试结果偏移。
比如第一次测试后,静态列表已经存储了大量素数,第二次调用stream()时,迭代到2、3等小素数时,要么被isPrime()直接判定为非素数(如果你的逻辑是仅新增未出现的素数),要么重复添加(导致异常或冗余),最终流的输出序列完全偏离预期。
解决方案
1. 用实例化的素数生成器替代静态变量
把素数列表和生成逻辑封装在一个内部类中,每次调用stream()时创建新的生成器实例,确保每个流拥有独立的素数状态,互不干扰。
示例代码:
import java.util.ArrayList; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; public class PrimeStream { public static IntStream stream() { // 每次调用stream()都创建新的生成器,状态独立 PrimeGenerator generator = new PrimeGenerator(); return Stream.generate(generator::nextPrime) .mapToInt(Integer::intValue); } private static class PrimeGenerator { private final List<Integer> primes = new ArrayList<>(); private int current = 2; public int nextPrime() { // 单独处理第一个素数2,之后只迭代奇数提升效率 if (current == 2) { primes.add(2); current = 3; return 2; } while (true) { if (isPrime(current)) { primes.add(current); int result = current; current += 2; return result; } current += 2; } } private boolean isPrime(int n) { for (int p : primes) { // 用long避免p*p溢出 if ((long) p * p > n) { break; } if (n % p == 0) { return false; } } return true; } } }
2. 优化性能满足百万素数要求
上面的实现通过跳过偶数(除了2)减少了一半的判断次数,同时用(long)p*p避免整数溢出,确保判断逻辑正确。对于百万素数的生成需求,试除法在优化后可以达到题目要求的几秒内完成的性能。
关键说明
- 静态变量的全局共享性是问题根源,改用实例变量后,每个流的生成过程完全独立,不会受之前调用的影响。
- 用
Stream.generate结合有状态的生成器,替代无状态的IntStream.iterate+filter,可以更好地控制素数生成的状态流转。
内容的提问来源于stack exchange,提问作者Hector Williams
相关产品推荐
相关产品推荐

