Я получаю несколько наборов результатов из базы данных и сохраняю каждую строку как объект типа 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
}
В настоящее время я сохраняю полученные объекты в Map<Integer, List<DbRow>>
, чтобы разделить их определенным свойством (в данном случае clientNumber
, все DbRow
с определенным номером клиента хранятся в List<DbRow>>
* в то время как их ключ - это определенный номер клиента).
Мне нужно создать из него Map<Integer, Map<String, Map<LocalDate, Integer>>>
, что я сейчас делаю, используя много строк кода.
Желаемый результат можно описать как
количество различных контрактных дат за месяц поглощения на номер клиента
(например, Map<
номер клиента , Map<
месяц захвата , Map<
дата контракта ,
количество >>>
)
где месяцем поглощения является String
формата "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);
});
Кто-нибудь знает (если есть) способ сделать это более коротким способом, используя потоковый API? Я действительно хочу иметь красивое решение для этого.