I have a simple DTO class:
@Builder
public class AccountDto {
private Long id;
private BigDecimal balance;
private Currency currency;
}
Currency
is an enum
of my own which maintains about 300 different currency symbols.
For testing purposes, I want to create 10 AccountDTO
s that correspond to one currency, then 10 that correspond to another, and so on and so forth. The following code generates some sequential IDs:
public static final Map<Currency, List<Long>> ACCOUNT_IDS_OF_GIVEN_CURRENCIES = Map.of(
Currency.USD, LongStream.rangeClosed(1L, 10L).boxed().toList(),
Currency.GBP, LongStream.rangeClosed(11L, 20L).boxed().toList(),
Currency.EUR, LongStream.rangeClosed(21L, 30L).boxed().toList(),
Currency.INR, LongStream.rangeClosed(31L, 40L).boxed().toList()
);
Now, I would like to create AccountDTO
instances based on these IDs that I generated into another map keyed by the exact same Currency
instances. While I could do it like this:
public static final Map<Currency, List<AccountDto>> ACCOUNT_DTOS_OF_GIVEN_CURRENCIES = generateAccountDTOsBasedOnIds(ACCOUNT_IDS_OF_GIVEN_CURRENCIES);
public static Map<Currency, List<AccountDto>> generateAccountDTOsBasedOnIds(Map<Currency, List<Long>> inputMap){
Map<Currency, List<AccountDto>> accountDtosOfGivenCurrencies = new HashMap<>();
for(Map.Entry<Currency, List<Long>> entry : inputMap.entrySet()){
accountDtosOfGivenCurrencies.put(entry.getKey(), entry.getValue().stream()
.map(id->AccountDto.builder()
.id(id)
.balance(BigDecimal.TEN)
.currency(entry.getKey())
.build())
.collect(Collectors.toList()));
}
return accountDtosOfGivenCurrencies;
}
This is rather imperative and inelegant, explicitly allocating a HashMap
, whereas no such thing was necessary for the ACCOUNT_IDS_OF_GIVEN_CURRENCIES
Map
. I am trying to do this in one fell swoop, using streams, Map.ofEntries()
, entrySet()
, Map.Entry.copyOf()
(Java 17 feature) and other ways, but so far I have failed. The closest I've come to is the following, which fails at compile-time because Map.entry()
is not an instantiable type.
public static final Map<Currency, List<AccountDto>> ACCOUNT_DTOS_OF_GIVEN_CURRENCIES = Map.ofEntries(
ACCOUNT_IDS_OF_GIVEN_CURRENCIES.entrySet().stream().map(currencyListEntry -> Map.entry(currencyListEntry.getKey(),
currencyListEntry.getValue().stream().map(id->
AccountDto.builder()
.id(id)
.balance(BigDecimal.TEN)
.currency(currencyListEntry.getKey())
.build())
.toList())).toArray(Map.Entry::new));
Any ideas about how this could be solved elegantly and without an intermediate instantiation of a Map
type like HashMap
or TreeMap
? Completely open to solutions that might use ApacheCommons, Guava, any reasonable library I could add to my pom
. Thanks.
You can use the toMap
collector.
public static final Map<Currency, List<AccountDto>> ACCOUNT_DTOS_OF_GIVEN_CURRENCIES =
ACCOUNT_IDS_OF_GIVEN_CURRENCIES
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().stream()
.map(id -> AccountDto.builder().id(id)
.balance(BigDecimal.TEN).currency(e.getKey()).build())
.toList()));