编辑 - 第二类没有基于索引的访问权限,而是实现可迭代
假设这样的类结构:
public class Values
{
public int getValue(int i)
{
return values_[i];
}
private int[] values_;
}
和第二类这样的
public class ValuesCollection implements Iterable
{
private Values[] valuesCollection_;
}
有没有办法使用java8流API来操作每个维度的统计数据,例如:sum,mean,min,max,range,variance,std等。例如[[2,4,8],[1, 5,7],[3,9,6]],为了获得最小值,它将返回[1,4,6]
我能想出的最接近的是:
public int[] getMin(ValuesCollection valuesCollection)
{
IntStream.range(0, valuesCollection.size()).boxed().collect(Collectors.toList())
.forEach(i -> {
List<Integer> vals = valuesCollection.stream()
.map(values -> values.getValue(i))
.collect(Collectors.toList());
// operate statistics on vals
// no way to return the statistics
});
}
答案 0 :(得分:2)
你可以做到。我使用的是数组,而不是你的包装类。此外,我可能应该包含一些验证,即数组是矩形的,并使用orElseThrow
而不是getAsInt
,但你明白了。
int[][] vals = {{2, 4, 8}, {1, 5, 7}, {3, 9, 6}};
int[] min = IntStream
.range(0, vals[0].length)
.map(j -> IntStream.range(0, vals.length).map(i -> vals[i][j]).min().getAsInt())
.toArray();
System.out.println(Arrays.toString(min)); // Prints [1, 4, 6] as expected
(因为我使用过数组,所以我可以用这行代替
.map(j -> Arrays.stream(vals).mapToInt(arr -> arr[j]).min().getAsInt())
但我写的就是像我一样对你的情况进行密切建模,你的对象不是数组,但确实有基于索引的访问。)
为标准差做这件事显然更难,但你可以把我的答案与this one结合起来。
修改强>
如果您的外部类没有基于索引的访问权限,而是实现Iterable
,则可以将Iterable
转换为Stream
。
Iterable<int[]> vals = Arrays.asList(new int[][] {{2, 4, 8}, {1, 5, 7}, {3, 9, 6}});
int[] min = IntStream
.range(0, vals.iterator().next().length)
.map(j -> StreamSupport.stream(vals.spliterator(), false).mapToInt(a -> a[j]).min().getAsInt())
.toArray();
System.out.println(Arrays.toString(min)); // Prints [1, 4, 6] as expected
答案 1 :(得分:1)
你可以通过简单地将Integer [] []展平为Integer []然后以等于数组长度的周期对其进行操作来实现。 以下算法仅执行min,max,sum !!
public class Test {
public static void main(String... strings) {
Integer[][] vals = {{2, 4, 8}, {1, 5, 7}, {3, 9, 6}};
BinaryOperator<Integer> minFunction = (x, y) -> x < y? x: y;
BinaryOperator<Integer> maxFunction = (x, y) -> x > y? x: y;
BinaryOperator<Integer> sumFunction = (x, y) -> x+y;
Integer[] performStatistic = performStatistic(vals, minFunction); // 1 4 6
Integer[] performStatistic2 = performStatistic(vals, maxFunction); // 3 9 8
Integer[] performStatistic3 = performStatistic(vals, sumFunction); // 6 18 21
}
public static Integer[] performStatistic(Integer[][] vals, BinaryOperator<Integer> f){
List<Integer> res = new ArrayList<>(vals.length);
int[] i = {0};
Arrays.asList(vals).stream().flatMap((Integer[] x)-> Arrays.asList(x).stream())
.forEach(x -> {
if(i[0]<vals.length){
res.add(i[0], x);
}else{
int cyclicPos = i[0]%vals.length;
res.set(cyclicPos, f.apply(res.get(cyclicPos), x));
}
i[0]++;
});
return res.toArray(new Integer[res.size()]);
}
}
要执行其他操作,您可以按照相同的步骤操作,并使用BiFunction<Integer,Double,Double>
执行范围,差异......
也许以下可以帮助你!!
double avg = 100; // the avg you can get it from the previous algorithm
BiFunction<Integer,Double,Double> varianceFunction = (Integer x, Double y) -> {
return Math.pow(new Double(x) - avg, 2)+y;
};// after getting the result just divided it by the (size of the array -1)