Java - 分组&使用Lambdas求和

时间:2016-06-19 08:32:48

标签: java lambda java-stream

我正在尝试实现分组&数组中值的求和。在下面显示的数据中,“附加费”栏下的值需要与日期相加 - 注意组合&存储在另一个列表中。

我提到了Link1 Link2& Link3但无法弄清楚我在做什么错。希望我所面临的问题是明确的,等待指导。

数据(从excel读取):

  • 日期|注意事项编号|收费
  • 2016年1月29日| 1234 | 12.2
  • 2016年1月29日| 1234 | 10.5
  • 2016年1月28日| 2468 | 9.25
  • 2016年1月28日| 2468 | 14.4
  • 2016年1月28日| 2468 | 13.3
  • 2016年1月27日| 1357 | 17.2
  • 2016年1月27日| 1357 | 18.7

代码数据模型:

public class ModelSurcharge {
private LocalDate cNoteDate;
private int cNote;
private double surcharge;

public ModelBrokerage(LocalDate cNoteDate, int cNote, double surcharge) {
    this.cNoteDate = cNoteDate;
    this.cNote = cNote;
    this.surcharge= surcharge;
}

public LocalDate getcNoteDate() {
    return cNoteDate;
}

public int getcNote() {
    return cNote;
}

public double getSurcharge() {
    return surcharge;
}
}

代码主类:

File fileCNote = null;
try {
     fileCNote = new File("c:/surcharge.xlsx");
} catch (IOException e) {
     e.printStackTrace();
}
// Read data from excel file
List<List<XSSFCell>> dataSurcharge = iFaceXLSX.readData(fileCNote);
// Skip header line & filter out rows which do not have surcharge amount
dataSurcharge = dataSurcharge .stream().skip(1).filter(p -> p.get(6).getNumericCellValue() > 0).collect(Collectors.toList());

// Transfer data read from excel to the data model
List<ModelSurcharge> surcharges= new ArrayList<>();
dataSurcharge.forEach(e -> {
     List<ModelSurcharge> temp = Arrays.asList(new ModelSurcharge(
                e.get(0).getDateCellValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                (int) e.get(1).getNumericCellValue(),
                (e.get(3).getNumericCellValue() + e.get(4).getNumericCellValue()) * e.get(6).getNumericCellValue()));
        surcharges.addAll(temp);
    });

//Output to console
    surcharges.stream().collect(groupingBy(Function.identity(),
            ()->new TreeMap<>(
                    Comparator.<ModelSurcharge,LocalDate>comparing(p->p.getcNoteDate()).thenComparing(p->p.getcNote())),
            Collectors.summingDouble(foo->foo.getSurcharge())))
            .forEach((group,surcharge) ->
                    System.out.println(group.getcNoteDate()+"\t"+group.getcNote()+"\t"+surcharge));

// Collecting to another list does not work
List<ModelSurcharge> output = surcharges.stream()
            .collect(groupingBy(p -> p.getcNoteDate(), Collectors.summingDouble(p -> p.getSurcharge())));

错误:

Cannot resolve method 'getcNoteDate()'
Cannot resolve method 'getSurcharge()'

1 个答案:

答案 0 :(得分:2)

您的ModelSurcharge课程没有编译,因为它有一个名为ModelBrokerage的构造函数。主代码的开头也不编译:文件构造函数永远不会抛出任何IOException。

但整个编译问题可以简化为以下代码,这些代码更简洁,并且不依赖于外部库:

public class ModelSurcharge {
    private LocalDate cNoteDate;
    private int cNote;
    private double surcharge;

    public ModelSurcharge(LocalDate cNoteDate, int cNote, double surcharge) {
        this.cNoteDate = cNoteDate;
        this.cNote = cNote;
        this.surcharge = surcharge;
    }

    public LocalDate getcNoteDate() {
        return cNoteDate;
    }

    public int getcNote() {
        return cNote;
    }

    public double getSurcharge() {
        return surcharge;
    }

    public static void main(String[] args) {
        List<ModelSurcharge> surcharges= new ArrayList<>();
        List<ModelSurcharge> output = surcharges.stream()
                                                .collect(groupingBy(p -> p.getcNoteDate(), 
                                                                    Collectors.summingDouble(p -> p.getSurcharge())));
    }
}

错误消息具有误导性。但这是因为编译器尝试从上下文中推断出p的类型,但它不能因为您尝试分配右侧表达式而导致到List<ModelSurcharge>,虽然groupingBy生成地图,而不是列表。对输出变量(Map<LocalDate, Double>)使用正确的类型,错误将消失。