类中数组上的java reduce
我尝试使用reduce对HashMap值求和类中数组上的java reduce,java,arrays,java-8,java-stream,final,Java,Arrays,Java 8,Java Stream,Final,我尝试使用reduce对HashMap值求和 public class Link { private double[] flows; public Link(double[] f) { setFlows(f); } public double[] getFlows() { return flows; } public void setFlows(double[] flows) { this.flow
public class Link
{
private double[] flows;
public Link(double[] f) {
setFlows(f);
}
public double[] getFlows() {
return flows;
}
public void setFlows(double[] flows) {
this.flows = flows;
}
public static void main(String argv[])
{
// TEST for reduce on HashMap
HashMap<Integer, Link> id1 = new HashMap<Integer, Link>();
id1.put(1, new Link(new double[]{10,1,30}));
id1.put(2, new Link(new double[]{20,2,3}));
id1.put(3, new Link(new double[]{30,2,3}));
id1.put(4, new Link(new double[]{40,2,30}));
double[] my_sum = new double[3];
for (int i=0; i < 3; ++i)
{
my_sum[i] = id1.entrySet().stream().mapToDouble(e->e.getValue().getFlows()[i]).sum();
}
assert(my_sum[0] == 100);
assert(my_sum[1] == 7);
assert(my_sum[2] == 66);
}
}
公共类链接
{
私人资金流动;
公共链接(双[]f){
设定流量(f);
}
公共双[]getFlows(){
回流;
}
公共void集合流(双[]流){
this.flows=flows;
}
公共静态void main(字符串argv[])
{
//在HashMap上测试reduce
HashMap id1=新建HashMap();
id1.put(1,新链接(新的双[]{10,1,30}));
id1.put(2,新链接(新的双[]{20,2,3}));
id1.put(3,新链接(新双[]{30,2,3}));
id1.put(4,新链接(新双[]{40,2,30}));
double[]我的总和=新的double[3];
对于(int i=0;i<3;++i)
{
my_sum[i]=id1.entrySet().stream().mapToDouble(e->e.getValue().getFlows()[i]).sum();
}
断言(my_sum[0]==100);
断言(my_sum[1]==7);
断言(my_sum[2]==66);
}
}
在for循环中,我想对Link类中每个数组项的值求和。但是,我有以下问题:
封闭范围中定义的局部变量必须是final或有效final
基本上,我不想将最终变量定义为类成员,如何解决它
还是有更好的方法来求和?(没有for循环?你走错了路:你不应该有一个外部的
for
循环,而应该在流管道中处理所有事情
你可以让它工作
在下面的代码中,只保留映射的值(因为我们对键不感兴趣)。然后将每个值映射到它们的流。最后,首先创建一个由3个元素组成的数组(初始化为0),然后将两个双数组合并成一个结果数组,将相同索引处的值相加,从而减少生成的流
我们必须依赖于在索引上使用流,因为没有内置的工具将两个流压缩在一起
double[] my_sum =
id1.values().stream()
.map(Link::getFlows)
.reduce(
new double[3],
(v1, v2) -> IntStream.range(0, v2.length).mapToDouble(i -> v1[i] + v2[i]).toArray()
);
System.out.println(Arrays.toString(my_sum)); // prints [100.0, 7.0, 66.0]
你走错了路:你不应该有一个外部的for
循环,而应该处理流管道中的所有事情
你可以让它工作
在下面的代码中,只保留映射的值(因为我们对键不感兴趣)。然后将每个值映射到它们的流。最后,首先创建一个由3个元素组成的数组(初始化为0),然后将两个双数组合并成一个结果数组,将相同索引处的值相加,从而减少生成的流
我们必须依赖于在索引上使用流,因为没有内置的工具将两个流压缩在一起
double[] my_sum =
id1.values().stream()
.map(Link::getFlows)
.reduce(
new double[3],
(v1, v2) -> IntStream.range(0, v2.length).mapToDouble(i -> v1[i] + v2[i]).toArray()
);
System.out.println(Arrays.toString(my_sum)); // prints [100.0, 7.0, 66.0]
如果您添加了一个add
方法(不幸的是,使链接变为可变的),那么您也可以使用链接
进行求和
// Makes it mutable - will try immutable later
public void add(Link other) {
for (int i = 0; i < flows.length; i++) {
flows[i] += other.flows[i];
}
}
public static void main(String argv[]) {
// TEST for reduce on HashMap
HashMap<Integer, Link> id1 = new HashMap<>();
id1.put(1, new Link(new double[]{10, 1, 30}));
id1.put(2, new Link(new double[]{20, 2, 3}));
id1.put(3, new Link(new double[]{30, 2, 3}));
id1.put(4, new Link(new double[]{40, 2, 30}));
Link sum = new Link(new double[3]);
id1.entrySet().stream().forEach(l -> sum.add(l.getValue()));
}
//使其可变-稍后将尝试不可变
公共无效添加(链接其他){
for(int i=0;isum.add(l.getValue());
}
如果您添加了一个add
方法(不幸的是,使链接变为可变链接),那么您也可以使用链接
作为总和
// Makes it mutable - will try immutable later
public void add(Link other) {
for (int i = 0; i < flows.length; i++) {
flows[i] += other.flows[i];
}
}
public static void main(String argv[]) {
// TEST for reduce on HashMap
HashMap<Integer, Link> id1 = new HashMap<>();
id1.put(1, new Link(new double[]{10, 1, 30}));
id1.put(2, new Link(new double[]{20, 2, 3}));
id1.put(3, new Link(new double[]{30, 2, 3}));
id1.put(4, new Link(new double[]{40, 2, 30}));
Link sum = new Link(new double[3]);
id1.entrySet().stream().forEach(l -> sum.add(l.getValue()));
}
//使其可变-稍后将尝试不可变
公共无效添加(链接其他){
for(int i=0;isum.add(l.getValue());
}
另一种对我来说更好的选择是使用数组。setAll
:
double[] my_sum = new double[3];
Arrays.setAll(my_sum,
i -> id1.entrySet().stream().mapToDouble(e->e.getValue().getFlows()[i]).sum());
这里的i
实际上是最终的。我觉得更好的替代方法是使用数组。setAll
:
double[] my_sum = new double[3];
Arrays.setAll(my_sum,
i -> id1.entrySet().stream().mapToDouble(e->e.getValue().getFlows()[i]).sum());
这里的i
实际上是最终的。可能是这里的变量i
。尝试在循环内定义最终副本,例如final int k=i
,然后在lambda中使用getFlows()[k]
。还可以使用后缀增量运算符:对于循环,i++前缀与中的后缀一样有效。这里可能是变量i
。尝试在循环内定义最终副本,例如final int k=i
,然后在lambda中使用getFlows()[k]
。还可以使用后缀增量运算符:对于循环,i++前缀的效果与中的后缀一样好。作为旁注,您需要以某种方式确保所有数组的长度相同。您可以在Link的构造函数中检查长度。作为旁注,您需要以某种方式确保所有数组的长度相同。你可以在Link的构造器中检查一下长度。谢谢。这里的语法更简单。谢谢。这里的语法更简单。