【问题标题】:Java - Grouping & Summing using LambdasJava - 使用 Lambda 进行分组和求和
【发布时间】:2016-06-19 08:32:47
【问题描述】:

我正在尝试实现数组中值的分组和求和。在下面显示的数据中,附加费列下的值需要为日期 - 注释组合求和并存储在另一个列表中。

我提到了Link1Link2Link3,但无法弄清楚我在做什么错误。希望我面临的问题很清楚,等待指导。

数据(从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()'

【问题讨论】:

  • 您能否通过删除所有链接和不相关的代码片段来简化和澄清您的问题,并仅提供相关代码:ModelSurcharge 类,一个完整但最小的示例,显示无法编译的代码,以及准确完整的编译器错误消息?
  • @JBNizet 我已按照您的通知进行了更改。我希望我已经提供了必要的信息并且我面临的问题更加清楚。向您和论坛道歉

标签: java lambda java-stream


【解决方案1】:

您的ModelSurcharge 类无法编译,因为它有一个名为ModelBrokerage 的构造函数。主代码的开头也无法编译:File 构造函数从不抛出任何 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&lt;ModelSurcharge&gt;,尽管groupingBy生成地图,而不是列表。对输出变量(Map&lt;LocalDate, Double&gt;)使用正确的类型,错误就会消失。

【讨论】:

  • 谢谢。我错过了地图的使用。但是使用 Map 我将无法获得注释编号。我应该如何使用 Map 函数来获取所有 3 列的数据。我想我应该按 LocalDate 和 Integer 分组,不知道如何实现。
  • 写另一个问题,像我一样将代码减少到最少,并解释你真正想要得到的输出。
  • 好的,想通了。我使用了 Map。再次感谢您的帮助。
猜你喜欢
  • 2014-12-08
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
相关资源
最近更新 更多