我在尝试使用Java 8进行开发。我尝试将这个for循环转换为Java 8流操作时遇到了一些困难。
for (int y = 0; y < 5; y ++) {
for (int x = y; x < 10; x += 2) {
System.out.println(x+y);
}
}
Please help!
我在尝试使用Java 8进行开发。我尝试将这个for循环转换为Java 8流操作时遇到了一些困难。
for (int y = 0; y < 5; y ++) {
for (int x = y; x < 10; x += 2) {
System.out.println(x+y);
}
}
Please help!
将嵌套循环转换的规范方式是在流上使用flatMap
,例如:
IntStream.range(0, 5).flatMap(i->IntStream.range(i, 10))
.forEach(System.out::println);
对于您的任务而言,最棘手的部分是增量加2,因为在流API中没有直接的等价物。有两种可能性:
使用 IntStream.iterate(y, x->x+2)
定义起始值和增量。然后通过限制元素数量来修改无限流:.limit((11-y)/2)
。
因此,您的循环的最终代码如下:
IntStream.range(0, 5)
.flatMap(y->IntStream.iterate(y, x->x+2).limit((11-y)/2)
.map(x -> x+y)).forEach(System.out::println);
使用IntStream.range(0, (11-y)/2)
创建一个升序的int
流,并使用.map(t->y+t*2)
修改它以产生所需的内部for
循环的值。
然后,你的循环的结果代码将如下所示:IntStream.range(0, 5)
.flatMap(y->IntStream.range(0, (11-y)/2).map(t->y+t*2).map(x -> x+y))
.forEach(System.out::println);
IntStream.range(a, b)
,然后使用 filter(n -> n % 2 == 0)
过滤掉奇数,从而生成一个 +2
变体。 - skiwiy
的最大值(考虑到你总是从0开始)x
的最大值(考虑到你总是从0开始)y
的增量操作。(假设+1没有固定)x
的增量操作。x
和 y
的操作。private void doMyDoubleLoop(
final int yEnd, final IntUnaryOperator yIncrementOperator,
final int xEnd, final IntUnaryOperator xIncrementOperator,
final IntBinaryOperator combiner, final IntConsumer consumer
) {
for (int y = 0; y < yEnd; y = yIncrementOperator.applyAsInt(y)) {
for (int x = y; x < xEnd; x = xIncrementOperator.applyAsInt(x)) {
consumer.accept(combiner.applyAsInt(x, y));
}
}
}
用途:
doMyDoubleLoop(5, y -> y + 1, 10, x -> x + 2, (x, y) -> x + y, System.out::println);
就像我所说的,这可能有点过度,所以假设所有与for循环相关的问题都已经解决,那么它会突然变得更加美好:
private void doMyInternalDoubleLoop(final IntBinaryOperator combiner, final IntConsumer consumer) {
for (int y = 0; y < 5; y++) {
for (int x = y; x < 10; x += 2) {
consumer.accept(combiner.applyAsInt(x, y));
}
}
}
用途:
doMyInternalDoubleLoop((x, y) -> x + y, System.out::println);
如果您有一个类,其中有很多使用这个双循环的操作,但不想复制循环,那么我建议使用这种模式,因为这符合DRY(不要重复自己)原则。
IntStream
上的filter
方法来完成此操作:IntStream
.range(0, 5)
.flatMap(
y ->
IntStream
.range(y, 10)
.filter(x -> (x-y) % 2 == 0)
.map(x -> x+y))
.forEach(System.out::println);
IntStream
.range(first, last)
.filter(index -> (index-first) % segment == 0)
.forEach(
System.out.printf(
"Doing segment %s to %s%n",
index,
Math.min(index+seg-1, last)));
我还在努力理解这个问题。以下代码不太优美:
IntStream.range(0, 5).forEach(y ->
//<kludge>
//I would appreciate it if someone would replace this with something smarter.
IntStream.iterate(y, x -> x + 2)
.limit(100)
.filter(x -> x < 10)
//</kludge>
.forEach( x -> System.out.println(y+x)));
“x += 2”是复杂的部分,如果range方法有一个“增量”参数就会变得简单。我使用“iterate”来自行增加值,但“iterate”会产生一个无限的流。我用“filter”将其限制在所需范围内,并放置了一个任意的“limit”,以便它不会溢出并开始输出小于10的大负数。