根据您的场景,拥有小数据集或大数据集,您可能希望按顺序或并行处理项目。
注意:以下代码包含JUnit @Test 注释和AssertJ 断言。
解决方案:顺序、一次通过、小数据集
此解决方案解析数组并跟踪最大和当前最大索引。如果找到新的最大值,则清除索引并插入新的最大值索引。
@Test
public void sequential_algorithm_return_max_with_indexes() {
int[] values = new int[]{42, 3, 42, 42, 42, 5, 8};
int maxValue = Integer.MIN_VALUE;
List<Integer> maxValueIndexes = new ArrayList<>();
for (int index = 0; index < values.length; index++) {
int value = values[index];
if (value == maxValue) {
maxValueIndexes.add(index);
} else {
if (value > maxValue) {
maxValue = value;
maxValueIndexes.clear();
maxValueIndexes.add(index);
}
}
}
assertThat(maxValue).isEqualTo(42);
assertThat(maxValueIndexes).containsExactly(0, 2, 3, 4);
}
解决方案:并行、大数据集
流很灵活,允许并行处理。
下面的数据表示为一对索引值而不是数组。这样做是为了将对数组转换为流并跟踪索引。
因为这应该并行工作,reduce 方法接受 3 个参数 - 初始值、累加器和组合器。这意味着多个存储桶并行运行。对于每个桶,都有一个初始值和一个累加器,用于按顺序处理项目。然后使用 combiner 参数组合桶的并行结果。
@Test
public void parallel_algorithm_return_max_with_indexes() {
Pair<Integer, Integer>[] values = new Pair[]{
new Pair<>(0, 42),
new Pair<>(1, 3),
new Pair<>(2, 42),
new Pair<>(3, 42),
new Pair<>(4, 42),
new Pair<>(5, 5),
new Pair<>(6, 8),
};
ValueIndexes<Integer> maxValueIndexes = Arrays.stream(values)
.parallel()
.reduce(
new ValueIndexes<>(Integer.MIN_VALUE),
(ValueIndexes<Integer> valueIndexes, Pair<Integer, Integer> value) -> {
if (valueIndexes.getValue() == value.getValue()) {
valueIndexes.addIndex(value.getKey());
} else {
if (value.getValue() > valueIndexes.getValue()) {
valueIndexes = new ValueIndexes<>(value.getValue());
valueIndexes.addIndex(value.getKey());
}
}
return valueIndexes;
},
(valueIndexes1, valueIndexes2) -> {
if (valueIndexes1.getValue() == valueIndexes2.getValue()) {
ValueIndexes<Integer> valueIndexes = new ValueIndexes<>(valueIndexes1.getValue());
valueIndexes.addIndexes(valueIndexes1.getIndexes());
valueIndexes.addIndexes(valueIndexes2.getIndexes());
return valueIndexes;
} else {
if (valueIndexes1.getValue() > valueIndexes2.getValue()) {
return valueIndexes1;
} else {
return valueIndexes2;
}
}
}
);
assertThat(maxValueIndexes.getValue()).isEqualTo(42);
assertThat(maxValueIndexes.getIndexes()).containsExactlyInAnyOrder(0, 2, 3, 4);
}
private class ValueIndexes<T> {
private T value;
private List<Integer> indexes = new ArrayList<>();
public ValueIndexes(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public Iterable<Integer> getIndexes() {
return indexes;
}
public void addIndexes(Iterable<Integer> indexes) {
indexes.forEach(this::addIndex);
}
public void addIndex(int index) {
indexes.add(index);
}
}