Reputation: 4267
I have this kind of values inside a Map:
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1,"mark");
map.put(2,"1.1");
map.put(3,"google");
map.put(4,"12");
map.put(5,"2.2);
I need to order this Map, ordering both numbers and strings.
What I get now is this (as you can see numbers are not "ordered" since are String)
1.1
12
2.2
google
mark
What I should get is:
1.1
2.2
12
google
mark
How can I do it? I'm a little confused.
Upvotes: 1
Views: 81
Reputation: 11050
If you really need a map you can use a LinkedHashMap
which is sorted by insertion order. To compare the values you can create your own comparator:
Comparator<String> stringAndNumberComparator = (s1, s2) -> {
try {
return Double.valueOf(s1).compareTo(Double.valueOf(s2));
} catch (NumberFormatException e) {
return s1.compareTo(s2);
}
};
Now you can use a java stream to sort the entry set of your map and collect it back to a LinkedHashMap
:
Map<Integer, String> sorted = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue(stringAndNumberComparator))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (s1, s2) -> s1, LinkedHashMap::new));
Alternatively you can use the comparator provided in the answer from Karol Dowbecki with Map.Entry.comparingByValue()
.
The result will be {2=1.1, 5=2.2, 4=12, 3=google, 1=mark}
;
If you just need a list of your values you can just use this:
List<String> sorted = map.values().stream()
.sorted(stringAndNumberComparator)
.collect(Collectors.toList());
The result in this case will be [1.1, 2.2, 12, google, mark]
.
Upvotes: 1
Reputation: 44960
You can't order a Map
by entry value. SortedMap
e.g. TreeMap
allows to order the entries by key. It seems you might be using a wrong data structure.
In your example you can define a function that will leniently parse a double
and return Double.NaN
instead of an exception:
private double lenientParseDouble(String s) {
try {
return Double.parseDouble(s);
} catch (NumberFormatException ex) {
return Double.NaN;
}
}
As per Double.compare()
docs:
Double.NaN
is considered by this method to be equal to itself and greater than all other double values (includingDouble.POSITIVE_INFINITY
).
and then use it as part of the Comparator
chain
map.values().stream()
.sorted(Comparator.comparingDouble(this::lenientParseDouble).thenComparing(Function.identity()))
.forEach(System.out::println);
Upvotes: 5