如何获取列表,将其收集到地图中,然后使用Java Streams进行排序



我有以下代码。。。。

public Map<Object, Integer> getRankings(){
Stream<String> stream = votes.stream();
return stream
.collect(Collectors.toMap(s -> s, s -> 1, Integer::sum));
}

这很好,但现在我想根据计数对地图进行排序。我在收集后尝试了排序,但该方法不可用,因为流现在是一个映射。在退货之前我该如何分类?我可以用Stream来做吗?还是必须像地图一样排序?

映射基本上是未排序的。因此,你不能暗示命令。

然而,map的一些特定子类确实包含了排序的定义。关键是,java.util.Map本身没有,所以我们必须深入研究子类;例如,new java.util.HashMap不能订购,句点。

LinkedHashMap是按"插入顺序"排序的,因此,您可以强制执行它的顺序。

SortedMap类(如TreeMap(在键上使用比较器进行排序,因此也不可能根据值对它们进行排序。

一般的答案是你遇到了一些问题X,然后想:我知道!我将通过一个按值排序的映射来解决这个未知问题X!但这不太可能是解决X的好方法。不幸的是,你没有说X是什么,你只是在问如何在java中根据值排序地图的问题,因此我们现在陷入了困境:哦,这真的很难做到。

万一你仍然认为你的"按值排序的地图"想法是如何解决X:

没有.toLinkedHashMapCollectors.toMap有一个变体,它有第四个参数,即为您制作映射的lambda。使用该函数,传入一个lambda,该lambda生成new LinkedHashMap。然后您需要强制流API以正确的顺序插入,这是不可能的。

因此,我们需要使这成为可能:首先收集到一张简单的简地图。然后,通过询问该映射的入口集并在其上进行流传输,将其重新旋转为流。然后,将该流转换为已排序的流,在entry.getValue()上进行排序。然后,使用Collectors.toMap方法之一将生成的顺序排序流收集回映射中,该方法允许您提供mapSupplier。您不需要在这里对toMap进行分组——您的流对象已经准备好逐字插入了。

当然,这是低效的,并且有一个中间阶段映射,然后立即被扔进垃圾桶。但这是唯一的方法,这可以追溯到:根据值对地图进行排序相当棘手。

这个解决方案有效,但我会检查更多的;streamy";方法

public Map<Object, Integer> getRankings(){
Stream<String> stream = votes.stream();
Map<Object, Integer> map = stream
.collect(Collectors.toMap(s -> s, s -> 1, Integer::sum));
return Vote.sortByValues(map);
}
public static <K, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) {
Comparator<K> valueComparator =  new Comparator<K>() {
public int compare(K k1, K k2) {
int compare = map.get(k2).compareTo(map.get(k1));
if (compare == 0) return 1;
else return compare;
}
};
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
sortedByValues.putAll(map);
return sortedByValues;
}

相关内容

最新更新