Reputation: 480
I have an entity
public class Report {
private String departmentName;
private BigDecimal amount;
private String currency;
}
and I want to calculate the amount for each department depending on the currency and write the result in the line. Example:
List<Report> list = new ArrayList<>();
list.add(new Report("Moscow", new BigDecimal(100), "USD"));
list.add(new Report("Moscow", new BigDecimal(100), "USD"));
list.add(new Report("Paris", new BigDecimal(100), "USD"));
list.add(new Report("Moscow", new BigDecimal(200), "RUR"));
Result: "Moscow 200 usd, Paris 100 USD, Moscow 200 RUR"
For it:
Map<String, Map<String, String>> collect = list.stream().collect(
Collectors.groupingBy(doc -> doc.getDepartmentName(),
Collectors.groupingBy(Report::getCurrency,
Collectors.collectingAndThen(Collectors.toList(), doc -> {
BigDecimal sum = doc.stream()
.map(A::getAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
String cur = doc.stream().map(Report::getCurrency)
.findFirst().get();
return sum.toString() + " " + cur;
}))));
And I receive a result:
{Paris={USD=100 USD}, Moscow={USD=200 USD, RUR= 200 RUR}} -- correct
but I don't know how to convert Map<String, Map<String, String>> to String
Upvotes: 0
Views: 661
Reputation: 40024
Desired result is
"Moscow 200 usd, Paris 100 USD, Moscow 200 RUR"
Try it like this using flatMap.
String result = map.entrySet().stream()
.flatMap(e -> e.getValue().entrySet().stream()
.map(e2 -> e.getKey() + " " + e2.getValue()))
.collect(Collectors.joining(", "));
System.out.println(result);
prints
Paris 100 USD, Moscow 200 RUR, Moscow 200 USD
Note: Since maps are unordered, the order of the elements may not be consistent from run to run based on sums, additional Reports, etc.
I don't know if your Map is required as is or a way to get the result, but you could also do it like this.
Map<String, Map<String, BigDecimal>> map =
list.stream()
.collect(Collectors.groupingBy(
Report::getDepartmentName,
Collectors.toMap(Report::getCurrency,
Report::getAmount, BigDecimal::add)));
e2.getKey()
) to that.String result = map1.entrySet().stream().flatMap(e -> e
.getValue().entrySet().stream()
.map(e2 -> e.getKey() + " " + e2.getValue().toString()
+ " " + e2.getKey()))
.collect(Collectors.joining(", "));
Upvotes: 3