有没有办法使以下代码更通用?

时间:2015-07-10 22:21:20

标签: java java-8 gson java-stream

我正在使用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会更好。

3 个答案:

答案 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();
}