我有以下代码,由于必须将长流转换为数组,因此存在性能问题。 Board.getReachables() 方法返回一个流,因此能够使用流执行此 while 循环会提高性能。然而,我不确定如何继续。
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++;
}
将循环转换为流:
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();
}
counter
转换为 AtomicInteger
,因为它是在 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++;
}
我认为有人不应该这样做,但这是一个有趣的练习。
有两件事可以提高性能:
.forEach
上调用 Stream
。if
而不是 .filter()
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++;
}