Staram się stworzyć mapę
Map<AccountType, Map<User, BigDecimal>>
jednak udało mi się stworzyć mapę z kluczem obudowanym w Streamy.
Map<Stream<Stream<AccountType>>, Map<User, BigDecimal>>
Chcę wyciągnąć mapę gdzie kluczem jest typ rachunku a wartością mapa mężczyzn posiadających ten rachunek, gdzie kluczem jest obiekt User a wartością suma pieniędzy. Oto jak to zrobiłem:
Map<Stream<Stream<AccountType>>, Map<User, BigDecimal>> getMapWithAccountTypeKeyAndSumMoneyForManInPLN() {
return getCompanyStream() // 1
.collect(Collectors.toMap(
company -> company.getUsers() // 2
.stream()
.map(user -> user.getAccounts() // 3
.stream()
.map(Account::getType)), // 4
this::manWithSumMoneyOnAccounts // 5
));
}
- pobieram stream firm
- z firmy wyciągam użytkowników
- z użytkowników wyciągam konta
- i z kont wyciągam typ, czyli teoretycznie mam tutaj jako klucz AccountType w mapie zewnętrznej
- przekazuję firmę do tej metody, ta metoda zwraca wartość dla mapy wewnętrznej Map<User, BigDecimal>
private Map<User, BigDecimal> manWithSumMoneyOnAccounts(final Company company) { // 6
return company
.getUsers() // 7
.stream()
.filter(user -> user.getSex().equals(Sex.MAN)) // 8
.collect(Collectors.toMap(
Function.identity(), // 9
this::getSumUserAmountInPLN // 10
));
}
- przekazana firma z metody powyżej
- pobieram użytkowników
- filtruję że biorę pod uwagę tylko mężczyzn
- tworzę mapę wewnętrzną, ta metoda zwraca mi obiekt User więc w teorii mam klucz User w mapie wewnętrznej
- wywołuję funkcję do zliczania przekazując obiekt konkretnego użytkownika, zwraca mi wartość dla mapy wewnętrznej
private BigDecimal getSumUserAmountInPLN(final User user) {
return user.getAccounts()
.stream()
.map(this::getAccountAmountInPLN)
.reduce(BigDecimal.ZERO, BigDecimal::add); // 11
}
- policzona kwota, która zwraca BigDecimal czyli jest to ta wartość do mapy wewnętrznej
Company zawiera List< User> users czyli firma zawiera listę użytkowników,
User zawiera List<Account> accounts czyli użytkownik zawiera listę kont,
Account zawiera AccountType type (AccountType to enum) i Account zawiera Currency currency (Currency to też enum) czyli konto zawiera typ konta i walutę, zawiera także kwotę rachunku w typie BigDecimal
Zacząłem jeszcze inaczej do tego podchodzić, mniej więcej w taki sposób:
Map<AccountType, Map<User, BigDecimal>> getMapWithAccountTypeKeyAndSumMoneyForManInPLN() {
Predicate<User> isMan = m -> m.getSex() == Sex.MAN;
return getUserStream()
.filter(isMan)
.collect(Collectors.groupingBy(Account::getType),
Collectors.mapping(Function.identity(), this::getSumUserAmountInPLN));
}
jednak tutaj nawet nie mogę skompilować bo mam np informację dla klucza w mapie zewnętrznej Non-static method cannot be referenced from a static context, a inaczej nie mogę się dobrać do typu konta, więc raczej to jest nie ta droga.