将Java while循环转换为流以提高性能

将Java while循环转换为流以提高性能,java,stream,Java,Stream,我有以下代码,由于必须将长流转换为数组,因此存在性能问题。getReachables()方法返回一个流,因此在使用流进行循环时能够实现这一点会更好。然而,我不确定如何进行 int counter = 1; while (check(board, counter)) { for (int i = 0; i < board.length; i++) { if (board[i] == counter) { for (Pos reach2 :

我有以下代码,由于必须将长流转换为数组,因此存在性能问题。getReachables()方法返回一个流,因此在使用流进行循环时能够实现这一点会更好。然而,我不确定如何进行

 int counter = 1;
 while (check(board, counter)) {
   for (int i = 0; i < board.length; i++) {
     if (board[i] == counter) {
       for (Pos reach2 :
            Board.getReachables(currentTurn.getBoard().pos(i),
                                currentTurn.getBoard())
                 .toArray(Pos[]::new)) {
         if (board[currentTurn.getBoard().index(reach2)] == 0) {
           board[currentTurn.getBoard().index(reach2)] = counter + 1;
         }
       }
     }
   }
   counter++;
 }
int计数器=1;
while(支票(董事会、柜台)){
对于(int i=0;i
将循环转换为流:

AtomicInteger counter = new AtomicInteger(1);
while (check(board, counter.get())) {
   for (int i = 0; i < board.length; i++) {
     if (board[i] == counter.get()) {
         Board.getReachables(currentTurn.getBoard().pos(i), currentTurn.getBoard())
         .filter(reach2 ->  board[currentTurn.getBoard().index(reach2)] == 0)
         .forEach(reach2 -> board[currentTurn.getBoard().index(reach2)] = counter.get() + 1);
     }
   }
   counter.incrementAndGet();
 }
AtomicInteger计数器=新的AtomicInteger(1);
while(检查(board,counter.get()){
对于(int i=0;iboard[currentTurn.getBoard().index(reach2)]==0
.forEach(reach2->board[currentTurn.getBoard().index(reach2)]=计数器.get()+1);
}
}
counter.incrementAndGet();
}
计数器
转换为
原子整数
,因为它在lambda中引用,因此必须是有效的最终计数器


其他重构留给读者。

未经测试,只是一个想法:

    while (check(board, counter)) {
        final int finalCounter = counter; //counter has to be final,
        //otherwise you get a "Local variable counter defined in an enclosing scope must be final or effectively final" error

        Arrays.stream(board) //IntStream
        .filter(b -> b == finalCounter) //  if (board[i] == counter) {
        .mapToObj(i ->Board.getReachables(currentTurn.getBoard().pos(i), currentTurn.getBoard())) //returns Stream<Stream<Pos>>
        .flatMap(Function.identity()) // flatmap maps Stream<Stream<Pos>> to a single (combined) Stream<Pos>
        .filter(pos -> board[currentTurn.getBoard().index(pos)] == 0)  //board[currentTurn.getBoard().index(reach2)] == 0
        .forEach(fp -> board[currentTurn.getBoard().index(fp)] = finalCounter +1); //board[currentTurn.getBoard().index(reach2)] = counter + 1;
        counter++;
    }
while(检查(板、计数器)){
final int finalCounter=counter;//计数器必须是final,
//否则会出现“在封闭范围中定义的局部变量计数器必须是final或实际上是final”错误
Arrays.stream(board)//IntStream
.filter(b->b==finalCounter)//if(板[i]==计数器){
.mapToObj(i->Board.getReachables(currentTurn.getBoard().pos(i),currentTurn.getBoard())//返回流
.flatMap(Function.identity())//flatMap将流映射到单个(组合)流
.filter(pos->board[currentTurn.getBoard().index(pos)]==0)//board[currentTurn.getBoard().index(reach2)]==0
.forEach(fp->board[currentTurn.getBoard().index(fp)]=finalCounter+1);//board[currentTurn.getBoard().index(reach2)]=计数器+1;
计数器++;
}

我不认为有人应该这样做,但这是一个有趣的练习。

有两件事可以提高性能:

  • 不要创建数组并在其上循环,只需在
    流上调用
    .forEach
  • 只计算一次索引。不幸的是,这意味着使用
    if
    而不是
    .filter()
  • int计数器=1;
    while(支票(董事会、柜台)){
    对于(int i=0;i{
    int index=当前转辙机索引(reach2);
    如果(线路板[索引]==0){
    board[索引]=下一个计数器;
    }
    返回;
    });
    }
    }
    计数器++;
    }
    
    大多数情况下,流并不比传统的while循环快……看看这个……你能添加你的线路板和Pos类吗?然而……在这种情况下,代码是将一个流转换成一个数组,然后迭代数组。嗯,线路板和Pos类超过400行,我将尝试找出相关的方法dsI不确定这是否必要。请稍等。我正在寻找答案。好的,非常感谢:)这是一个简洁的解决方案,比我的解决方案更有效。Thank.np。您可以通过引入一个值为
    currentTurn.getBoard()的变量来整理代码
    ,也可能是
    计数器+1
    循环中的另一个变量,将
    计数器
    保留为
    整数
    ,以绕过“有效最终”问题。但是,我尽力将转换为1到1,以便集中精力解决问题。我现在正在测试这一点,它似乎是迄今为止最有效的解决方案:)我可能说得太早了。我正在使用一个具有动态深度的搜索树,虽然这在深度1上似乎是最有效的,但它一走就会变慢s在搜索树的下方更深。但是,这可能是因为代码的速度使树更深更快,这可能是我的动态深度函数的错误。我将继续测试您可以尝试使用Arrays.stream(board).parallel()而不是Arrays.stream(board)…有时更快,但有时更慢…你还必须检查你的逻辑在并行执行时是否工作我已经在并行执行计算,将搜索树拆分为不同的线程。不过,将此方法拆分可能比拆分搜索树更聪明。
            int counter = 1;
            while (check(board, counter)) {
                for (int i = 0; i < board.length; i++) {
                    if (board[i] == counter) {
                        Board currentTurnBoard = currentTurn.getBoard();
                        int   nextCounter      = counter + 1;
                        Board.getReachables(currentTurnBoard.pos(i), currentTurnBoard)
                             .forEach(reach2 -> {
                                 int index = currentTurnBoard.index(reach2);
                                 if (board[index] == 0) {
                                     board[index] = nextCounter;
                                 }
                                 return;
                             });
                    }
                }
                counter++;
            }