【问题标题】:sort map by key - explanation按键排序地图 - 解释
【发布时间】:2019-09-30 03:42:12
【问题描述】:

我想对包含这种格式数据的文本文件进行排序:

A 8
B 2
C 5

通过它的价值。所以我发现了这个:

Map<String, Long> getSortedLinkedHashMappedRankingArray(String[] rankingArray) {
    return Arrays
            .stream(rankingArray)
            .map(it -> it.split("\\s+"))
            .collect(Collectors.toMap(it -> it[FIRST_PART], it -> Long.valueOf(it[SECOND_PART])))
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
}

除了上次的收集操作,我几乎都懂了:

.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new))

你能解释一下这里发生了什么吗? oldValue 和 newValue 是什么以及它是如何工作的?

另外,我想听听我在collect 操作之前是否理解正确。

  1. 首先,我们创建给定数组的流。
  2. 然后我们用空格分割数组的每个元素,这样我们 可以将名称作为键和数字作为映射中的值。
  3. 然后我们创建地图元素集并创建流。
  4. 然后我们按值排序。

对吗?

PS:我在看Java Sort map by key explanation,但没看懂。

【问题讨论】:

  • 你读过Collectors.toMap()(有3个参数的那个)的Javadoc吗?
  • @Eran 是的,我做到了
  • 那么在“一个收集器中不清楚的地方,它将元素收集到一个 Map 中,其键是对输入元素应用键映射函数的结果,其值是应用 a值映射函数到等于键的所有输入元素并使用合并函数将它们组合“?您似乎在询问合并功能。
  • @Eran 我不明白它是如何工作的。我的意思是,我们getKey,我们getValue,然后我们进行一些合并。换句话说,这个公式根本不清楚,可能太技术性了。
  • 假设您已经在地图中有条目 (key1,value1)。现在,收集器正在尝试将条目 (key1,value2) 放入映射中。它看到键已经存在,所以它应用了合并函数:(oldValue, newValue) -> oldValue,这意味着 (value1, value2) -> value1(即保留原始值并丢弃新值)。

标签: java sorting dictionary


【解决方案1】:

(oldValue, newValue) -&gt; oldValue, LinkedHashMap::new) lambda 表达式是合并函数,它应用于具有相同键的两个值。在这种情况下,它返回第一个值并丢弃第二个值。

也就是说,您的代码效率低下,因为您正在创建两个 Maps 并运行两个 Stream 管道。你可以用一个来达到同样的效果:

Map<String, Long> getSortedLinkedHashMappedRankingArray(String[] rankingArray) {
    return Arrays
            .stream(rankingArray)
            .map(it -> it.split("\\s+"))
            .map(arr -> new SimpleEntry<> (arr[FIRST_PART], Long.valueOf(arr[SECOND_PART])))
            .sorted(Map.Entry.comparingByValue())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
}

【讨论】:

  • SimpleEntry 在那里做什么?
  • @pipilam java.util.AbstractMap.SimpleEntryMap.Entry 接口的简单实现。我没有创建一个 Map 然后通过它的 entrySet 流式传输,而是直接创建一个条目流。
  • @pipilam 也许你应该试试new SimpleEntry&lt;String,Long&gt;(...)
【解决方案2】:

第三个参数java doc

     *    a merge function, used to resolve collisions between
     *                      values associated with the same key, as supplied
     *                      to {@link Map#merge(Object, Object, BiFunction)}
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new))

如果有重复的键,选择前一个,或者新的

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多