I am looking for some help in grouping a list of objects from a list with multiple keys.
Basically, I have a list of users which contains a list of their orders and I want to be able to group them together using UserName and Address as the keys.
Example Data:
<UserList>
<User>
<Username>user123</Username>
<Address>London</Address>
<TransactionList>
<TransactionList>
<OrderNumber>1</OrderNumber>
<Cost>3683446.6600</Cost>
</TransactionList>
</TransactionList>
</User>
<User>
<Username>user123</Username>
<Address>London</Address>
<TransactionList>
<TransactionList>
<OrderNumber>3</OrderNumber>
<Cost>500</Cost>
</TransactionList>
</TransactionList>
</User>
<User>
<Username>user12356</Username>
<Address>Manchester</Address>
<TransactionList>
<TransactionList>
<OrderNumber>6</OrderNumber>
<Cost>90000</Cost>
</TransactionList>
</TransactionList>
</User>
<User>
<Username>user12356</Username>
<Address>Manchester</Address>
<TransactionList>
<TransactionList>
<OrderNumber>10</OrderNumber>
<Cost>100</Cost>
</TransactionList>
</TransactionList>
</User>
</UserList>
I want to order it like this so that each user just has one instance and its related transactions are grouped in a list based off Username and Address:
<UserList>
<User>
<Username>user123</Username>
<Address>London</Address>
<TransactionList>
<TransactionList>
<OrderNumber>1</OrderNumber>
<Cost>3683446.6600</Cost>
</TransactionList>
<TransactionList>
<OrderNumber>3</OrderNumber>
<Cost>500</Cost>
</TransactionList>
</TransactionList>
</User>
<User>
<Username>user12356</Username>
<Address>Manchester</Address>
<TransactionList>
<TransactionList>
<OrderNumber>6</OrderNumber>
<Cost>90000</Cost>
</TransactionList>
<TransactionList>
<OrderNumber>10</OrderNumber>
<Cost>100</Cost>
</TransactionList>
</TransactionList>
</User>
</UserList>
I have tried to do it using a map:
Map<String, Map<String,List<User>>> map;
map = userLists.getUserList().stream()
.collect(Collectors.groupingBy(User::getUserName, Collectors.groupingBy(User::getAddress)));
This is slightly what I am looking to do but I was wondering if there was a better way using MultiKey Map or something like that and then iterate through and put a list of transactions if the key matched.
Thanks in advance for the help.
Your approach is not wrong, the first step is correct: to group the users by the
userName
and thenaddress
. Personally, I'd invert it since more likely there are more users with a same address, but the order is not important in terms of achieving a corect result.I notice the expected output looks like
List<User>
with reduced users with common characteristic (userName
andaddress
) and concatenatedtransactionList
lists. Although a map with a composite key (ex.${userName}_${address}
) might seem helpful, I'd rather choose theList<User>
, which is in comppliant with, by the way, what the expected output is like.So, the second step is to iterate all these entries and reduce
List<User>
within theMap
into a single user. Each inner entry will be associated with a single user (because of bothuserName
andaddress
). For-each is more than suitable for this task. There you go:The Stream API is a good for grouping to get an intermediate result, however, for such futher reduction it would be very clumsy.