将for循环转换为java8流
我在玩Java8。我在将这个for循环转换为Java8流时遇到了一些问题将for循环转换为java8流,java,functional-programming,java-8,java-stream,Java,Functional Programming,Java 8,Java Stream,我在玩Java8。我在将这个for循环转换为Java8流时遇到了一些问题 for (int y = 0; y < 5; y ++) { for (int x = y; x < 10; x += 2) { System.out.println(x+y); } } for(int y=0;yx+2) .限额(100) .过滤器(x->xSystem.out.println(y+x)); x+=2是一个棘手的部分,如果range方法有一个“increme
for (int y = 0; y < 5; y ++) {
for (int x = y; x < 10; x += 2) {
System.out.println(x+y);
}
}
for(int y=0;y<5;y++){
对于(int x=y;x<10;x+=2){
系统输出打印项次(x+y);
}
}
请帮忙 我自己仍在努力解决这个问题。对于样式,以下内容不得分:
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)));
IntStream.range(0,5).forEach(y->
//
//如果有人能用更聪明的东西来代替它,我将不胜感激。
迭代(y,x->x+2)
.限额(100)
.过滤器(x->x<10)
//
.forEach(x->System.out.println(y+x));
x+=2
是一个棘手的部分,如果range方法有一个“increment”参数,那么这个部分就不重要了。我用iterate
自己做增量,但是iterate
生成一个无限流。我使用了filter
将其限制在我想要的范围内,并设置了一个任意的limit
,这样它就不会溢出并开始吐出大量小于10的负数。转换嵌套循环的标准方法是在流上使用flatMap
,例如
IntStream.range(0, 5).flatMap(i->IntStream.range(i, 10))
.forEach(System.out::println);
任务中棘手的部分是增量2,因为这在流API中没有直接的等价物。有两种可能性:
IntStream.iterate(y,x->x+2)
定义起始值和增量。然后您必须通过limit
ing元素的数量来修改无限流:.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, 5)
.flatMap(y->IntStream.range(0, (11-y)/2).map(t->y+t*2).map(x -> x+y))
.forEach(System.out::println);
IntStream.range(0,(11-y)/2)
创建所需数量的递增int
s流,并使用.map(t->y+t*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, 5)
.flatMap(y->IntStream.range(0, (11-y)/2).map(t->y+t*2).map(x -> x+y))
.forEach(System.out::println);
- 具有
最大值(考虑到您总是从0开始)y
- 具有
最大值(考虑到您总是从0开始)x
- 具有
增量操作的。(假设+1不是固定的)y
- 具有
增量操作的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));
}
}
}
正如我所说,这可能有点过头了,所以假设围绕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));
}
}
}
如果您有一个类,在该类上有大量使用此双循环的操作,但不想在循环中进行复制,我建议您使用此模式,因为这应该符合DRY(不要重复您自己)原则。我这样做的方法是在内部
IntStream
上使用筛选器
:
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)));
欢迎来到Stackoverflow!在这个网站上,我们喜欢互相帮助,但只有在你尝试了一些事情(并告诉我们这些事情)并做了一些事先的研究之后。谢谢你的评论,埃尔德克海泽。是的,在我来问之前我自己做了一些研究。外部for循环很简单。range(0,5).forEach()就可以了。但是步长为2的内部循环让我很反感……你也可以只取一个
IntStream.range(a,b)
,然后使用过滤器(n->n%2==0)
过滤掉不均匀的数字,从而生成一个+2
变量;afor
-循环:不。也许在这个简单的例子中,这可能很好。然而,一旦我们处理了更大的数据集,不要因为它看起来更简单而误以为可以对-循环使用。关于流的另一个有用的事实是,它们并不总是需要大量内存来操作。@JoD。只要“像循环一样的流”将很难编码,那么从维护的角度来看,最好避免它们,并使用常规循环,正如我所指出的。不要让事情变得过于复杂。如果你有一份10小时的工作,并且你知道你有机会将其缩短到一小时,那么你会坚持循环吗?请记住,许多人简化了发布问题的示例。我不认为有人会使用streams来构建带有输入字段的5x6矩阵-我的意思是,我希望不会出于您提到的相同原因。