转换地图<;整数,列表<;对象>&燃气轮机;映射<;整数,Map<;字符串,Map<;LocalDate,整数>&燃气轮机&燃气轮机;使用Java流API

转换地图<;整数,列表<;对象>&燃气轮机;映射<;整数,Map<;字符串,Map<;LocalDate,整数>&燃气轮机&燃气轮机;使用Java流API,java,java-stream,Java,Java Stream,我从数据库接收一些结果集,并将每一行存储为DbRow类型的对象,这是一个类: public class DbRow { private int clientNumber; private String recordNumber; private String takeoverMonth; private int takeovers; private int mainClaims; private int distinctContractDates

我从数据库接收一些结果集,并将每一行存储为
DbRow
类型的对象,这是一个类:

public class DbRow {

    private int clientNumber;
    private String recordNumber;
    private String takeoverMonth;
    private int takeovers;
    private int mainClaims;
    private int distinctContractDates;
    private LocalDate contractDate;

    public DbRow(int clientNumber, String recordNumber, String takeoverMonth, int takeovers,
                int mainClaims, int distinctContractDates, LocalDate contractDate) {
        super();
        this.clientNumber = clientNumber;
        this.recordNumber = recordNumber;
        this.takeoverMonth = takeoverMonth;
        this.takeovers = takeovers;
        this.mainClaims = mainClaims;
        this.distinctContractDates = distinctContractDates;
        this.contractDate = contractDate;
    }

    // getters & setters

    // hashCode, equals & toString
}
我当前将接收到的对象存储在
映射中
,以便通过特定属性将它们分开(在本例中,
clientNumber
,所有具有特定客户端编号的
DbRow
存储在
列表>
中,而它们的键是该特定客户端编号)

我需要用它创建一个
Map
,我目前使用了很多行代码

期望的结果可以描述为
每个客户编号每个接管月的不同合同日期计数
(如
Map

其中接管月份是格式为
“yyyy/MM”
字符串

我目前的解决方案很难看,但有效。它包含子映射的创建和填充,以及检查我想要删除的现有密钥。请看一下:

Map<Integer, List<DbRow>> records = new TreeMap<>();

// fill records with database results ...

Map<Integer, Map<String, Map<LocalDate, Integer>>> results = new TreeMap<>();

records.forEach((clientNumber, dbRows) -> {
    Map<String, List<DbRow>> rowsPerMonth = dbRows.stream()
                    .collect(Collectors.groupingBy(DbRow::getTakeoverMonth));
    Map<String, Map<LocalDate, Integer>> monthResults = new TreeMap<>();

    rowsPerMonth.forEach((takeoverMonth, rows) -> {
        if (monthResults.containsKey(takeoverMonth)) {
            Map<LocalDate, Integer> contractDateCount = monthResults.get(takeoverMonth);
            rows.forEach(dbRow -> {
                LocalDate contractDate = dbRow.getContractDate();
                if (contractDateCount.containsKey(contractDate)) {
                    int count = contractDateCount.get(contractDate);
                    count++;
                    contractDateCount.put(contractDate, count);
                } else {
                    contractDateCount.put(contractDate, 1);
                }
            });
            monthResults.put(takeoverMonth, contractDateCount);
        } else {
            Map<LocalDate, Integer> contractDateCount = new TreeMap<>();
            rows.forEach(dbRow -> {
                LocalDate contractDate = dbRow.getContractDate();
                if (contractDateCount.containsKey(contractDate)) {
                    int count = contractDateCount.get(contractDate);
                    count++;
                    contractDateCount.put(contractDate, count);
                } else {
                    contractDateCount.put(contractDate, 1);
                }
            });
            monthResults.put(takeoverMonth, contractDateCount);
        }
    });

    results.put(clientNumber, monthResults);
});
Map records=newtreemap();
//用数据库结果填充记录。。。
映射结果=新树映射();
records.forEach((clientNumber,dbRows)->{
Map rowserMonth=dbRows.stream()
.collect(Collectors.groupingBy(DbRow::getTakeoverMonth));
Map monthResults=new TreeMap();
rowsPerMonth.forEach((接管月,行)->{
if(每月结果containsKey(接管月)){
Map contractDateCount=monthResults.get(takeoverMonth);
rows.forEach(dbRow->{
LocalDate contractDate=dbRow.getContractDate();
if(合同日期计数。集装箱(合同日期)){
int count=contractDateCount.get(contractDate);
计数++;
contractDateCount.put(contractDate,count);
}否则{
contractDateCount.put(contractDate,1);
}
});
monthResults.put(接管月、合同日期计数);
}否则{
Map contractDateCount=新树映射();
rows.forEach(dbRow->{
LocalDate contractDate=dbRow.getContractDate();
if(合同日期计数。集装箱(合同日期)){
int count=contractDateCount.get(contractDate);
计数++;
contractDateCount.put(contractDate,count);
}否则{
contractDateCount.put(contractDate,1);
}
});
monthResults.put(接管月、合同日期计数);
}
});
结果。put(客户编号、月结果);
});

有人知道(如果有)一种使用流API以较短的方式完成此任务的方法吗?我真的很想为它找到一个漂亮的解决方案。

您可能正在寻找类似以下内容的解决方案:

Map<Integer, Map<String, Map<LocalDate, Long>>>  countDistinctDatesPerMonthPerClient(List<DbRow> input) {
    return input.stream()
            .collect(Collectors.groupingBy(DbRow::getClientNumber,
                    Collectors.groupingBy(DbRow::getTakeoverMonth,
                            Collectors.groupingBy(DbRow::getContractDate, Collectors.counting()))));
}
Map countdistinctdatespermonperClient(列表输入){
返回input.stream()
.collect(收集器.groupingBy(DbRow::getClientNumber、,
Collectors.groupby(DbRow::getTakeoverMonth,
Collectors.groupby(DbRow::getContractDate,Collectors.counting());
}

看起来像一个嵌套的
groupby
,带有
计数
用例。但老实说,要读取代码堆栈将需要一些空闲。考虑到嵌套的地图泛型,我会考虑将您的代码> map
作为某种契约提取。object@TobiasRoland是的,我也想到了这个想法…@Naman几周后再读一遍也要花很多时间,这就是为什么我在寻找更好的解决方案……这就是我一直在寻找的,除了数字类型(
Long
,而不是
Integer
),但这并不重要。谢谢