我正在使用gson序列化/反序列化和java 8流。以下是代码段
private long sumofTime() {
Line[] lines = gson.fromJson(jsonString, Line[].class);
return Arrays.stream(lines).filter(x -> x.hasTime())
.mapToInt(x -> x.getTime).sum();
}
线类看起来像,
public class Line {
String name;
String stamp;
Integer time;
Integer xx;
Integer yy;
Integer zz;
...
...
boolean hasTotalTime() {
return totalTime != null;
}
...
getters...setters...}
Stream用于检查每个数组元素(即Line)的特定变量(例如上例中的时间)是否为空,然后获取所有时间的总和。
问题:Line对象中有30个变量需要求和,因此如何使解更通用,而不是为每个变量编写求和方法。请注意,要处理的线对象超过1000个,这就是为什么我认为Stream会更好。
答案 0 :(得分:4)
您可以将函数传递给sum方法,以从您想要求和的每一行中获取值:
public int sumLines(Function<Line, Integer> extractor){
Line[] lines = ...
return Arrays.stream(lines).map(extractor)
.filter(Objects::nonNull).mapToInt(i -> i).sum();
}
....
int time = sumLines(Line::getTime);
这假定如果该属性不存在,该函数将返回null,但如果不是这样,您也可以传入Predicate
进行过滤。
答案 1 :(得分:2)
您尝试做的部分是动态属性提取,部分是部分应用的功能,在Java中这两者都不是特别简单。您最好以不同的方式定义Line
课程。我会使用Map
来存储属性,如:
public class Line {
Map<String, Integer> props;
public Line() {
// Initialize props
}
public boolean has(String prop) {
return props.containsKey(prop);
}
public Integer get(String prop) {
return props.get(prop);
}
public void set(String prop, Object value) {
return props.put(prop, value);
}
}
现在,当你正在寻找一堆东西的总和时,你可以打电话给
public int sumOf(Line[] lines, String prop) {
return Arrays.stream(lines)
.filter(l -> l.has(prop))
.reduce(0, Integer::sum);
}
答案 2 :(得分:1)
不是每个属性都有一个字段,你可以为属性定义一个枚举,然后从枚举到int的映射:
public enum LineAttribute {
XX,
YY,
ZZ,
...
}
private final EnumMap<LineAttribute, Integer> attributes;
public Line() {
attributes = new EnumMap<>(LineAttribute.class);
// init all attributes to 0
for (LineAttribute attr : LineAttribute.values()) {
attributes.put(attr, 0);
}
}
然后,您可以遍历每个属性,获取行的值并对这些值求和。
private long sumOf(LineAttribute attr) {
Line[] lines = gson.fromJson(jsonString, Line[].class);
return Arrays.stream(lines)
.filter(x -> x.has(attr))
.mapToInt(x -> x.get(attr))
.sum();
}