I am having the task of sorting Java Map by descending order of nested Array size/length, but the nested array is inside nested Map. The structure looks like:
HashMap<String, HashMap<String, ArrayList<String>>> classes = new HashMap<>();
.sorted((k1, k2) -> Long.compare(classes.get(k2.getKey()).entrySet().stream().count(), classes.get(k1.getKey()).entrySet().stream().count()))
.sorted((k1, k2) -> Integer.compare(k2.getValue().values().size(), k1.getValue().values().size()))
Your question is under-specified. If the values are
Maps you can’t just say that you want want to sort by their List’s size as there can be an arbitrary number of lists in each
Map. Your example given in the comments doesn’t clarify anything as it doesn’t address that issue at all. If you assume that the “slave” maps always have a size of one, you should specify that explicitly. Otherwise, you have to aggregate the sizes.
Further note that there are
static methods in the
Comparator interface for creating a comparator based on a property of the element to compare, thus you don’t need to write the code to extract the property twice.
So the solution summing the sizes of the lists may look like
classes.entrySet().stream() .sorted(Comparator.comparingInt(e -> e.getValue().values() .stream().mapToInt(Collection::size).sum())) .forEach(System.out::println);
Note that this aggregation also works if there is only one list in each “slave” map.
Just to be complete, note that specifically for sorting map entries, there are comparator factories in the
Map.Entry interface which may be used like
classes.entrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.comparingInt( m -> m.values().stream().mapToInt(Collection::size).sum()))) .forEach(System.out::println);
though in this specific case there is no benefit in using it. But if the actual value comparator is simpler, it may improve the code. There’s even a parameter-less variant (i.e.
Map.Entry.comparingByValue()) for the most trivial case that the map values are comparable.