简体   繁体   English

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

[英]How do I take a list, collect it to a map, then sort using Java Streams?

I have the following code....我有以下代码....

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

This works great but now I want to sort the map based on count.这很好用,但现在我想根据计数对 map 进行排序。 I tried a sort after the collect but the method isn't available because the stream is now a map.我在收集后尝试了排序,但该方法不可用,因为 stream 现在是 map。 How would I sort this before returning it?在返回之前我将如何对其进行排序? Can I do it using a Stream or do I have to sort as a map?我可以使用 Stream 还是必须排序为 map?

Maps are fundamentally unsorted.地图基本上是未排序的。 You cannot therefore imply an order.因此,您不能暗示订单。

However, some specific subclasses of map do include a definition of ordering.然而,map 的一些特定子类确实包含了排序的定义。 The point is, java.util.Map itself does not, so we must delve into the subclasses;重点是, java.util.Map本身没有,所以我们必须深入研究子类; For example, a new java.util.HashMap cannot be ordered , period.例如,不能订购new java.util.HashMap ,期间。

LinkedHashMap is sorted by 'insertion order', and thus, you can enforce an order for it. LinkedHashMap 按“插入顺序”排序,因此,您可以为其强制执行顺序。

SortedMap classes (such as TreeMap) are sorted on key , with a comparator, and therefore it is not possible to sort them on the value either. SortedMap 类(例如 TreeMap)是按key排序的,带有一个比较器,因此也不可能按 value 对它们进行排序。

The general answer is that you had some problem X and thought: I know.一般的答案是你遇到了一些问题 X 并想:我知道。 I'll fix this unknown problem X by having a map that is ordered by value, But it is highly unlikely that is a good way to solve X, Unfortunately, you didn't say what X is: you are merely asking questions about how to get a map sorted on values in java, and thus we're now stuck on.我将通过按值排序的 map 来解决这个未知问题 X,但这不太可能是解决 X 的好方法,不幸的是,你没有说 X 是什么:你只是在问关于如何得到一个 map 按 java 中的值排序,因此我们现在卡住了。 Ooooof, that is really hard to do. Oooooof,这真的很难做到。

Just in case you still think this 'map ordered on values' idea of yours is how to solve X:以防万一你仍然认为你的这个“按值排序的地图”的想法是如何解决 X:

There is no .toLinkedHashMap .没有.toLinkedHashMap There IS a variant of Collectors.toMap with a fourth argument which is a lambda that makes the map for you.有一个带有第四个参数的Collectors.toMap变体,它是 lambda,它为您生成 map。 Use that one, passing in a lambda that makes a new LinkedHashMap .使用那个,传入一个 lambda 来生成一个new LinkedHashMap Then you need to coerce the stream API to insert in the right order, which is impossible.然后你需要强制 stream API 以正确的顺序插入,这是不可能的。

So, we need to make that possible: First collect to a plain jane map.所以,我们需要使这成为可能:首先收集到一个普通的简 map。 Then re-spin that back out as a stream by asking that map for its entryset and streaming over it.然后通过询问 map 的入口集并在其上流式传输,将其重新旋转为 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ。 Then, turn that stream into a sorted stream, sorting on entry.getValue() .然后,将 stream 转换为排序后的 stream,在entry.getValue()上排序。 Then collect the resulting sequential sorted stream back into a map, using one of the Collectors.toMap methods that let you provide the mapSupplier.然后使用允许您提供 mapSupplier 的 Collectors.toMap 方法之一,将生成的顺序排序 stream 收集回 map。 You don't need the grouping toMap here - your stream objects are ready to be inserted verbatim.您不需要在此处分组 toMap - 您的 stream 对象已准备好逐字插入。

This is of course, inefficient and has an intermediate stage map which is then immediately tossed in the garbage.这当然是低效的,并且有一个中间阶段 map 然后立即被扔进垃圾箱。 But it's the only way to do this, which goes back: Having maps-sorted-on-value is rather tricky.但这是做到这一点的唯一方法,这可以追溯到:按值排序的地图相当棘手。

This solution works but I would give the check to a more "streamy" Way.该解决方案有效,但我会以更“流畅”的方式进行检查。

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何生成列表的 Map 的 Map(地图<string, map<enum, list<string> &gt;&gt;) 在 java 中使用流</string,> - How do I generate a Map of Map of List (Map<String, Map<Enum, List<String>>>) in java using streams 如何使用java8流对TreeSet的列表进行排序 - How do I sort a List of TreeSets with java8 streams 转换 Map <string,list<person> &gt; 至 Map <string,list<employee> &gt;,使用 Java 8 个流。 我这样做了,但是没有 for 循环怎么做</string,list<employee></string,list<person> - Convert Map<String,List<Person>> to Map<String,List<Employee>>, using Java 8 streams. I did this but how do this without for loop 使用流收集到Map - Using streams to collect to Map 如何使用java 8 lambda和streams对Map <YearMonth,List <LocalDate >>进行排序 - How to sort Map<YearMonth, List<LocalDate>> with java 8 lambda and streams 你如何转换地图 <String, Person> 到地图 <String, Integer> 在java流里面收集? - How do you convert Map<String, Person> to Map<String, Integer> in java streams inside collect? Java 流映射与副作用并收集或 foreach 并填充结果列表 - Java streams map with sideeffect and collect or foreach and populate a result-list Hashmap with Streams in Java 8 Streams 收集值 Map - Hashmap with Streams in Java 8 Streams to collect value of Map 使用带有 Java 流的收集和映射时出现“不兼容的类型”错误 - "Incompatible types" error when using collect and map with java streams 如何使用 Java 8 流 API 对列表进行排序和排序 - How to sort and order a list using the Java 8 streams API
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM