I have a map of Integers, I need to iterate all over the entries of the map to add them to a String, but first to all, I need to limit the results to a specific quantity, and then sort them based on the values of the map (that would be more efficient that first sort and then limit).
So, in order to do that, I'm using the java 8 Stream API and lambdas expressions, this is the code I wrote so far:
Map<Integer, Integer> allHighScoresPerLevel=highScores.get(levelId);
Set<Map.Entry<Integer, Integer>> sortedHighScores=allHighScoresPerLevel.entrySet()
.stream().limit(Configuration.MAX_HIGHSCORES_DISPLAYED)
.map((e)->e).sorted((o1,o2)->(o1.getValue().compareTo(o2.getValue())))
.collect(Collectors.toCollection(TreeSet::new));
But I'm getting the following exception:
java.util.concurrent.ConcurrentHashMap$MapEntry cannot be cast to java.lang.Comparable
I get it, a map Entry does not extends Comparable so there is no natural way to sort the entries, but I'm specificly providing a comparator (lambda) in the sorted method to teach how to sort the entries.
So I have two questions:
1) What is the right way to do this? what am I doing wrong?
2) Are Streams thread safe? I'm working in a multithreaded environment, so should I use a collector that returns a Tread safe Collection?
You are overcomplicating things: TreeSet needs a Comparator unless the objects are comparable (Map.Entrys are not comparable) and the sorting will be done by the TreeSet.
So something like this (with static imports):
Set<Entry<Integer, Integer>> sortedHighScores = allHighScoresPerLevel.entrySet().stream()
.limit(Configuration.MAX_HIGHSCORES_DISPLAYED)
.collect(toCollection(() -> new TreeSet<> (Entry.comparingByValue())));
You have not given enough information to know if the code is thread safe - but if the original map is thread safe you should be fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With