Я думаю, вам нужно что-то вроде этого:
List<Invoice> invoiceListForMonth = new ArrayList<>();
//add some data
Map<LocalDate, BigDecimal> result =
invoiceListForMonth.stream()
.collect(Collectors.groupingBy(
Invoice::getPurchaseDate
)).entrySet().stream()//This will return a map of Map<LocalDateTime, List<Invoice>>
.collect(Collectors.toMap(Map.Entry::getKey, // to collect with the date
e -> e.getValue().stream().map(Invoice::getPrice) //and the sum of
.reduce(BigDecimal.ZERO, BigDecimal::add)) // prices
);
Чтобы лучше это понять Вы можете разделить свою работу в два этапа:
Map<LocalDateTime, List<Invoice>> grouping =
invoiceListForMonth.stream()
.collect(Collectors.groupingBy(Invoice::getPurchaseDate));
Map<LocalDate, BigDecimal> result = grouping.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().stream().map(Invoice::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add))
);
Демонстрация конкретного примера
Заметьте, я использовал LocalDate
из java.time
API, потому что Date
устарел, и я больше не предлагаю его использовать.
Редактировать
на самом деле класс Invoice используется во многих других местах, поэтому я
не может изменить его на LocalDate. Я пытался реализовать это с помощью даты, но
моя коллекция сгруппирована по дате и времени. Я хочу сгруппировать используя
только дата Можете ли вы что-то предложить?
На основе вашего комментария вы можете создать свой собственный метод, который удалит часть времени из даты, чтобы вы могли сравнивать только часть даты следующим образом:
public static Date getDateWithoutTime(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
Затем вы можете вызвать метод в groupingBy
следующим образом:
Map<Date, List<Invoice>> grouping =
invoiceListForMonth.stream()
.collect(Collectors.groupingBy(
p -> getDateWithoutTime(p.getPurchaseDate())
));
Map<Date, BigDecimal> result = grouping.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().stream().map(Invoice::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add))
);
Примечание: я настоятельно не рекомендую использовать этот старый API, вместо этого вы можете перейти на java.time, это вам очень поможет.