我有一个Integers的地图,我需要遍历地图的所有条目以将它们添加到String中,但首先,我需要将结果限制为特定数量,然后根据它们对它们进行排序地图的价值(首先排序然后限制会更高效。)
所以,为了做到这一点,我使用java 8 Stream API和lambdas表达式,这是我到目前为止编写的代码:
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));
但我得到以下例外:
java.util.concurrent.ConcurrentHashMap$MapEntry cannot be cast to java.lang.Comparable
我明白了,一个映射条目没有扩展Comparable所以没有自然的方式对条目进行排序,但我特别在排序的方法中提供一个比较器(lambda)来教授如何对条目进行排序。
所以我有两个问题:
1)这样做的正确方法是什么?我做错了什么?
2)Streams线程是否安全?我在多线程环境中工作,所以我应该使用一个返回Tread安全集合的收集器吗?
答案 0 :(得分:9)
你过于复杂:TreeSet需要一个比较器,除非对象具有可比性(Map.Entrys不具有可比性),并且排序将由TreeSet完成。
这样的事情(使用静态导入):
Set<Entry<Integer, Integer>> sortedHighScores = allHighScoresPerLevel.entrySet().stream()
.limit(Configuration.MAX_HIGHSCORES_DISPLAYED)
.collect(toCollection(() -> new TreeSet<> (Entry.comparingByValue())));
您没有提供足够的信息来了解代码是否是线程安全的 - 但如果原始地图是线程安全的,那么您应该没问题。