Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将for循环转换为java8流_Java_Functional Programming_Java 8_Java Stream - Fatal编程技术网

将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

我在玩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;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);
    
  • 正如已经发生的那样,这肯定是可行的。但问题是:为什么 我怀疑是XY问题,流不是所有问题的解决方案,这是一个需要记住的重要事实

    看看你的代码在做什么,并创建一个方法来做你想做的事情,尽可能多的变化,你是:

    • 具有
      y
      最大值(考虑到您总是从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));
            }
        }
    }
    
    正如我所说,这可能有点过头了,所以假设围绕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
    变量;a
    for
    -循环:不。也许在这个简单的例子中,这可能很好。然而,一旦我们处理了更大的数据集,不要因为它看起来更简单而误以为可以对
    -循环使用
    。关于流的另一个有用的事实是,它们并不总是需要大量内存来操作。@JoD。只要“像循环一样的流”将很难编码,那么从维护的角度来看,最好避免它们,并使用常规循环,正如我所指出的。不要让事情变得过于复杂。如果你有一份10小时的工作,并且你知道你有机会将其缩短到一小时,那么你会坚持循环吗?请记住,许多人简化了发布问题的示例。我不认为有人会使用streams来构建带有输入字段的5x6矩阵-我的意思是,我希望不会出于您提到的相同原因。