Страхил Ахилов Страхил Ахилов - 11 months ago 63
Java Question

Sort by nested Array size inside nested Map

Hy everyone,
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<>();

I am using lambda and I tried many variations including:

.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()))

but without any luck. Because of the nature of the data I cannot use another data structure, I have to stick with this one.

Any ideas why my sorting is failing? Thanks for any help, I appreciate it.


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

    .sorted(Comparator.comparingInt(e -> e.getValue().values()

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

        m -> m.values().stream().mapToInt(Collection::size).sum())))

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.