我在下面的代码中使用嵌套 for 循环,并且有一些条件会破坏内部 for 循环,这提高了该代码的性能。
public static int getMaxValue(List<Integer> list) {
int result = -1;
for(int i=0; i<list.size(); i++) {
for(int j=i+1; j<list.size(); j++) {
if(list.get(j) - list.get(i) <= 0) break;
if(list.get(j) - list.get(i) > result) {
result = list.get(j) - list.get(i);
}
}
}
return result;
}
现在我如何使用 Java 8 流来执行相同的逻辑?我想出了下面的代码:
public static int getMaxValue(List<Integer> list) {
int[] result = { -1 };
IntStream.range(0, list.size()).forEach(i -> {
IntStream.range(i + 1, list.size()).forEach(j -> {
if(list.get(j) - list.get(i) <= 0) return;
if(list.get(j) - list.get(i) > result[0]) {
result[0] = list.get(j) - list.get(i);
}
});
});
return result[0];
}
这里我不能在java流中使用
break
语句,所以我使用了return
语句,但是仍然运行内部循环,因为它不会破坏它,性能没有提高。
如果我理解你的代码,你正在尝试找到输入列表中任意两个元素之间的最大成对差异。您可以使用
IntSummaryStatistics
来做到这一点:
public static int getMaxValue(List<Integer> list) {
IntSummaryStatistics stats = list.stream()
.mapToInt(Integer::intValue)
.summaryStatistics();
return stats.getMax() - stats.getMin();
}
这是一个 O(n) 操作,具有 O(1) 辅助存储。仍然不需要 O(n²) 操作。最终,尽早跳出循环是一种优化,但不是一种非常有效的优化 - 找到一种渐近成本较低的方法总是比提前跳出循环更更有效。
list.stream()
.mapToInt(Integer::intValue)
.max();
它将返回一个
OptionalInt
,您的列表为空。否则不确定你想用你的代码实现什么......
更新在Op澄清后
创建一个名为MinMax
的小类,它存储
min
和
max
,例如:
public class MinMax {
private final int min;
private final int max;
private MinMax(int min, int max) {
this.min = min;
this.max = max;
}
public int getDifference() {
return this.max - this.min;
}
public MinMax accept(int element) {
int newMin = element < min ? element : min;
int newMax = element > max ? element : max;
if (newMin != min || newMax != max) {
return new MinMax(newMin, newMax);
} else {
return this;
}
}
public static MinMax seed() {
return new MinMax(Integer.MAX_VALUE, Integer.MIN_VALUE);
}
}
这个新类负责跟踪最小值和最大值。 现在你可以做类似的事情:
int result = list.stream()
.reduce(MinMax.seed(), MinMax::accept())
.getDifference();