IntStream.iterate 具有要添加的交替值
IntStream.iterate with alternating values to add
我想创建一个整数序列,最好是 IntStream
,它遵循一定的条件。一些简单的例子来解释我想做什么:
从 0 开始的前 10 个偶数的序列(这里我没有问题,我用下面的代码片段来做)
IntStream.iterate(0, i -> i + 2).limit(10);
//0,2,4,6,8,10,12,14,16,18
从0开始的前10个数字的顺序,交替将2和3加到privious数字上;期望的输出:
//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()
实现与上面相同的效果?
对于三个或更多的交替值,我不知道如何优雅地做到这一点。例如,如果我想创建从 0 开始的前 10 个数字的序列,方法是将 +2、+5 和 +7 交替添加到具有所需输出的前一个数字:
//0,2,7,14,16,21,28,30,35,42
我考虑过在带有 3 个 if-else 块或 switch 情况的 for 循环中使用 i%3
但是当我需要更多交替值并且我必须添加更多 ifs
或cases
。任何想法如何去做?如果您认为 IntStream.iterate()
或 IntStream.generate()
不是解决所描述任务的正确方法,我也对其他方法持开放态度。
通过交替添加2或3来生成流,可以观察到每个other值都是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)
您可以使用 AtomicInteger
来实现这一点,并保留要以交替方式添加的数字列表。
List<Integer> adds = List.of(2,3,7);
AtomicInteger x = new AtomicInteger(0);
int limit = 10;
return IntStream.iterate(1,
i -> i + adds.get(x.getAndIncrement() % adds.size()))
.limit(limit)
.boxed()
.collect(Collectors.toList());
你可以从数学上看这个。假设您要交替添加 x1、x2、x3 ... xn。
前n项可以写成:
(0 * sum of all x's)
(0 * sum of all x's + x1)
(0 * sum of all x's + x1 + x2)
(0 * sum of all x's + x1 + x2 + x3)
...
(0 * sum of all x's + sum of all x's - xn)
接下来的n项可以用同样的方式写,除了你把所有的0都换成1。
(1 * sum of all x's)
(1 * sum of all x's + x1)
(1 * sum of all x's + x1 + x2)
(1 * sum of all x's + x1 + x2 + x3)
...
(1 * sum of all x's + sum of all x's - xn)
而 下一个 n 个术语,您将所有的 1 替换为 2,依此类推。
所以我们只需要生成流 (1, 2, 3, 4...) 和 flatMap
每个元素 i
到
的流
(i * sum of all x's)
(i * sum of all x's + x1)
(i * sum of all x's + x1 + x2)
(i * sum of all x's + x1 + x2 + x3)
...
(i * sum of all x's + sum of all x's - xn)
使用此模式,您可以像这样编写 2、5、7 流:
final int a = 2,
final int b = 5,
final int c = 7;
final int sum = a + b + c;
IntStream.iterate(0, i -> i + 1).flatMap(
i -> IntStream.of(i * sum, i * sum + a, i * sum + a + b)
).limit(10);
如果您想改为执行 2、3、5、7:
final int a = 2,
final int b = 3,
final int c = 5;
final int d = 7;
final int sum = a + b + c + d;
IntStream.iterate(0, i -> i + 1).flatMap(
i -> IntStream.of(i * sum, i * sum + a, i * sum + a + b, i * sum + a + b + c)
).limit(10);
我会留给你将其概括为任何 int[]
个数字。
我想创建一个整数序列,最好是 IntStream
,它遵循一定的条件。一些简单的例子来解释我想做什么:
从 0 开始的前 10 个偶数的序列(这里我没有问题,我用下面的代码片段来做)
IntStream.iterate(0, i -> i + 2).limit(10);
//0,2,4,6,8,10,12,14,16,18
从0开始的前10个数字的顺序,交替将2和3加到privious数字上;期望的输出:
//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()
实现与上面相同的效果?
对于三个或更多的交替值,我不知道如何优雅地做到这一点。例如,如果我想创建从 0 开始的前 10 个数字的序列,方法是将 +2、+5 和 +7 交替添加到具有所需输出的前一个数字:
//0,2,7,14,16,21,28,30,35,42
我考虑过在带有 3 个 if-else 块或 switch 情况的 for 循环中使用 i%3
但是当我需要更多交替值并且我必须添加更多 ifs
或cases
。任何想法如何去做?如果您认为 IntStream.iterate()
或 IntStream.generate()
不是解决所描述任务的正确方法,我也对其他方法持开放态度。
通过交替添加2或3来生成流,可以观察到每个other值都是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)
您可以使用 AtomicInteger
来实现这一点,并保留要以交替方式添加的数字列表。
List<Integer> adds = List.of(2,3,7);
AtomicInteger x = new AtomicInteger(0);
int limit = 10;
return IntStream.iterate(1,
i -> i + adds.get(x.getAndIncrement() % adds.size()))
.limit(limit)
.boxed()
.collect(Collectors.toList());
你可以从数学上看这个。假设您要交替添加 x1、x2、x3 ... xn。
前n项可以写成:
(0 * sum of all x's)
(0 * sum of all x's + x1)
(0 * sum of all x's + x1 + x2)
(0 * sum of all x's + x1 + x2 + x3)
...
(0 * sum of all x's + sum of all x's - xn)
接下来的n项可以用同样的方式写,除了你把所有的0都换成1。
(1 * sum of all x's)
(1 * sum of all x's + x1)
(1 * sum of all x's + x1 + x2)
(1 * sum of all x's + x1 + x2 + x3)
...
(1 * sum of all x's + sum of all x's - xn)
而 下一个 n 个术语,您将所有的 1 替换为 2,依此类推。
所以我们只需要生成流 (1, 2, 3, 4...) 和 flatMap
每个元素 i
到
(i * sum of all x's)
(i * sum of all x's + x1)
(i * sum of all x's + x1 + x2)
(i * sum of all x's + x1 + x2 + x3)
...
(i * sum of all x's + sum of all x's - xn)
使用此模式,您可以像这样编写 2、5、7 流:
final int a = 2,
final int b = 5,
final int c = 7;
final int sum = a + b + c;
IntStream.iterate(0, i -> i + 1).flatMap(
i -> IntStream.of(i * sum, i * sum + a, i * sum + a + b)
).limit(10);
如果您想改为执行 2、3、5、7:
final int a = 2,
final int b = 3,
final int c = 5;
final int d = 7;
final int sum = a + b + c + d;
IntStream.iterate(0, i -> i + 1).flatMap(
i -> IntStream.of(i * sum, i * sum + a, i * sum + a + b, i * sum + a + b + c)
).limit(10);
我会留给你将其概括为任何 int[]
个数字。