Reputation: 69
I have a Map
consisting of a String
and a corresponding List
. The lists have different sizes:
Map<String, List<String>> map = new LinkedHashMap<>();
List<String> l1 = new ArrayList<>();
List<String> l2 = new ArrayList<>();
List<String> l3 = new ArrayList<>();
l1.add("Str1");
l1.add("Str2");
l2.add("Str1");
l2.add("Str2");
l2.add("Str3");
l3.add("Str1");
map.put("Category A", l1);
map.put("Category B", l2);
map.put("Category C", l3);
I want to sort the entries of the Map
by the size of the List
s, in descending order. So in my example the final result should be:
Category B: Str1, Str2, Str3
Category A: Str1, Str2
Category C: Str1
I tried:
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
entry.getValue().sort(new Comparator<String>() {
public int compare(ArrayList a1, ArrayList a2) {
return a2.size() - a1.size();
}
});
But I get:
java: <anonymous com.app.class> is not abstract and does not override abstract method compare(java.lang.String,java.lang.String) in java.util.Comparator
Upvotes: 2
Views: 665
Reputation: 11120
You can introduce another instance of Map<K, V> (such that preserves an insertion order, e.g. LinkedHashMap<K, V>
), and insert the entries in it, in the order mandated by your comparator:
Map<String, List<String>> map = new LinkedHashMap<>();
List<String> l1 = new ArrayList<>();
List<String> l2 = new ArrayList<>();
List<String> l3 = new ArrayList<>();
l1.add("Str1");
l1.add("Str2");
l2.add("Str1");
l2.add("Str2");
l2.add("Str3");
l3.add("Str1");
map.put("Category A", l1);
map.put("Category B", l2);
map.put("Category C", l3);
LinkedHashMap<String, List<String>> descByValues = new LinkedHashMap<>();
map.entrySet()
.stream()
.sorted((e1, e2) -> e2.getValue().size() - e1.getValue().size())
.forEachOrdered(x -> descByValues.put(x.getKey(), x.getValue()));
and then:
descByValues
.forEach((k, v) -> System.out.println(k + ", " + v));
will output:
Category B, [Str1, Str2, Str3]
Category A, [Str1, Str2]
Category C, [Str1]
Upvotes: 4
Reputation: 11959
This won't do what you are trying to do:
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
entry.getValue().sort(new Comparator<String>() {
public int compare(ArrayList a1, ArrayList a2) {
return a2.size() - a1.size();
}
});
Your error is due to the type:
Map.Entry<String, List<String>> entry
This means that entry.getValue()
returns a List<String>
and also that List.sort(Comparator<T>)
works only with a Comparator<String>
because T = String
.
If you want to sort by the size of List, you will have to lose the category:
List<List<String>> list = new ArrayList<>(map.values());
list.sort((a1, a2) -> a2.size() - a1.size());
If you need to keep up the category, then you would need an intermediate type to keep the mapping:
List<Map.Entry<String, List<String>>> list = new ArrayList<>(map.entrySet());
list.sort((a1, a2) -> a2.getValue().size() - a1.getValue()..size());
Do note that I used a List rather than modifying the Map: not all map allows sorting, and those that allows sorting (SortedMap) mostly sort on the keys.
Upvotes: 1