I have the following data stored as lists:
List<ArrayList<String>> dummy = new ArrayList<>(); dummy.add(new ArrayList<>(List.of("1", "SP1", "SW1"))); dummy.add(new ArrayList<>(List.of("2", "SP1", "SW2"))); dummy.add(new ArrayList<>(List.of("3", "SP2", "SW1"))); dummy.add(new ArrayList<>(List.of("4", "SP2", "SW2"))); dummy.add(new ArrayList<>(List.of("5", "SP2", "SW1"))); dummy.add(new ArrayList<>(List.of("6", "SP1", "SW1"))); dummy.add(new ArrayList<>(List.of("7", "SP3", "SW2")));
I need to group it as follows
SW1-SP1-list{1,6} SW1-SP2-list{3,5} SW2-SP1-list{2} SW2-SP2-list{4} SW2-SP3-list{7}
What I have tried is the following:
var test = dummy.stream() .collect(Collectors.groupingBy( s -> s.get(2), TreeMap::new, Collectors.groupingBy( s -> s.get(1), Collectors.toList() ) ));
But this doesn’t give the desired result.
Advertisement
Answer
Here’s how you can apply nested groupingBy
Map<String, Map<String, List<String>>> result = dummy.stream() .collect(Collectors.groupingBy(l -> l.get(2), Collectors.groupingBy(l -> l.get(1), Collectors.mapping(l -> l.get(0), Collectors.toList()))));
To collect it in the order encountered, you can use a LinkedHashMap
,
Map<String, Map<String, List<String>>> result = dummy.stream() .collect(Collectors.groupingBy(l -> l.get(2), LinkedHashMap::new, Collectors.groupingBy(l -> l.get(1), LinkedHashMap::new, Collectors.mapping(l -> l.get(0), Collectors.toList())))); System.out.println(result);
Result:
{SW1={SP1=[1, 6], SP2=[3, 5]}, SW2={SP1=[2], SP2=[4], SP3=[7]}}