IntStream.iterate与要添加的交替值
我想创建一个整数序列,最好是一个IntStream遵循特定条件的 。一些简单的例子来解释我想要做什么:
从 0 开始的前 10 个偶数的序列(这里我没有问题,我用下面的代码片段来做)
IntStream.iterate(0, i -> i + 2).limit(10);
//0,2,4,6,8,10,12,14,16,18
前 10 个数字从 0 开始的序列,交替添加 2 和 3 到原始数字;所需的输出:
//0,2,5,7,10,12,15,17,20,22
我很愿意也使用了此方案 IntStream.iterate()还是IntStream.generate(),但不能让它在我自己的。我正在使用经典的 for 循环,它可以工作,但对于这样一个相对简单的任务来说有点长
List<Integer> list = new ArrayList<>();
list.add(0);
for(int i = 1, j = 1; i < 10; i++, j *= -1){
if(j > 0){
list.add(list.get(i-1) + 2);
}
else{
list.add(list.get(i-1) + 3);
}
}
//and then stream over the list to get IntStream
list.stream().mapToInt(Integer::intValue);
使用IntStream.iterate()或实现与上述相同的任何简单方法 IntStream.generate()?
对于三个或更多交替值,我不知道如何优雅地做到这一点。例如,如果我想通过将 +2、+5 和 +7 交替添加到具有所需输出的前一个数字来创建从 0 开始的前 10 个数字的序列:
//0,2,7,14,16,21,28,30,35,42
我曾想过i%3在带有 3 个 if-else 块或 switch case 的 for 循环中使用,但是当我需要更多交替值并且我必须添加更多ifs或cases. 任何想法如何做到这一点?如果您认为IntStream.iterate()或IntStream.generate()不是解决所描述任务的正确方法,我也愿意接受其他方法。
回答
以产生由交替加入2或3的流时,可以观察到,每一个其他值将是5的倍数。因此,如果先前的值是由5没有余整除,就要加2,否则,我们应该添加3。
IntStream.iterate(0, i -> (i % 5 == 0) ? (i + 2) : (i + 3)).limit(10)
对于两个交替的整数,会有这种方法不可行的情况。如果其中一个数字是另一个数字的因数,那将是不可能的。例如2和4。
对于此类情况,您可以使用更通用的方法并在迭代器之外维护一个布尔值。
它不遵循函数式风格,因为您的函数有副作用,但嘿,Java 不是函数式语言。它足够直观。
AtomicBoolean isTwo = new AtomicBoolean(true);
IntStream.iterate(0, i -> isTwo.getAndSet(!isTwo.get()) ? (i + 2) : (i + 4))
对于 3 个交替值,在一般情况下,您可以对布尔值执行类似的操作,但使用在 0、1 和 2 之间循环的整数计数器。
AtomicInteger counter = new AtomicInteger(0);
IntStream.iterate(0, i -> {
int count = counter.getAndUpdate(cnt -> (cnt + 1) % 3);
if (count == 0) return i + 2;
if (count == 1) return i + 5;
if (count == 2) return i + 7;
// As long as modulus value == number of if-conditions, this isn't possible
throw new RuntimeException("Only 3 possible values");
})
.limit(10)