使用Java 8流API和lambdas来操作地图

时间:2016-12-08 09:47:45

标签: java multithreading lambda java-8 java-stream

我有一个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安全集合的收集器吗?

1 个答案:

答案 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())));

您没有提供足够的信息来了解代码是否是线程安全的 - 但如果原始地图是线程安全的,那么您应该没问题。