【问题标题】:Java Sorting a Map using Steams VS TreeMapJava 使用 Steams VS TreeMap 对地图进行排序
【发布时间】:2019-01-19 04:00:23
【问题描述】:

考虑以下 Java HashMap。

Map<String, String> unsortMap = new HashMap<String, String>();
unsortMap.put("Z", "z");
unsortMap.put("B", "b");
unsortMap.put("A", "a");
unsortMap.put("C", "c");

现在我想按键排序这个地图。一种选择是我为此目的使用 TreeMap。

Map<String, String> treeMap = new TreeMap<String, String>(unsortMap);

另一个选项是我将 Java Streams 与 Sorted() 一起使用,如下所示。

Map<String, Integer> sortedMap = new HashMap<>();
unsortMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));

在这两个中,首选哪个选项以及为什么(可能是在性能方面)?

谢谢

【问题讨论】:

  • 您的第二个选项实际上不起作用。当然这应该算在内吗?
  • 我对 HashMaps 和 LinkedHashMaps 的了解很低。我从这篇文章中得到它,它实际上有正确的实现howtodoinjava.com/sort/java-sort-map-by-key
  • 有了上面的评论,请解释一下哪个选项更好?通过流排序的 LinkedHashMap 的 TreeMap
  • 苹果到橘子……它们不是同一个数据结构

标签: java dictionary hashmap


【解决方案1】:

正如其他人指出的那样,将排序的条目流转储到常规的 HashMap 不会做任何事情...LinkedHashMap 是合乎逻辑的选择。

但是,上述方法的替代方法是充分利用 Stream Collectors API。

Collectors 有一个toMap 方法,允许您为Map 提供替代实现。因此,您可以请求LinkedHashMap 而不是HashMap,如下所示:

unsortedMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .collect(Collectors.toMap(
       Map.Entry::getKey,
       Map.Entry::getValue,
       (v1, v2) -> v1, // you will never merge though ask keys are unique.
       LinkedHashMap::new
    ));

在使用 TreeMap 与 LinkedHashMap 之间......构造的复杂性可能与 O(n log n) 相同......显然,如果您打算继续添加更多,TreeMap 解决方案是更好的方法它的元素......我想在这种情况下你应该从TreeMap开始。 LinkedHashMap 选项的优点是,在链接或原始未排序地图上查找将是 O(1),而 TreeMap 类似于 O(log n),因此如果您需要保留未排序地图以进行有效查找,而如果您构建 LinkedHashMap,您可以扔掉原始未排序的地图(从而节省一些内存)。

要使用LinkedHashMap 使事情变得更高效,您应该在构造时提供所需大小的良好估算器,这样就不需要动态调整大小,因此您可以说LinkedHashMap::new 而不是LinkedHashMap::new

我认为TreeMap 的使用更简洁......因为可以使代码更小,所以除非存在可以使用未排序和排序的链接映射方法解决的实际性能问题,否则我会使用 @ 987654338@.

【讨论】:

  • 将它们添加到哈希图中将无济于事,因为它只会再次以随机顺序插入数据。
  • @SanathKumar...不确定您的意思...解决方案使用LinkedHashMap 而不是常规HashMap
  • 我试图解释为什么使用哈希图不起作用。它是为 op 而不是你。
【解决方案2】:

您的流代码甚至不会对地图进行排序,因为它正在对 HashMap 执行操作,而 HashMap 本质上是未排序的。为了使您的第二个流示例正常工作,您可以使用LinkedHashMap,它维护插入顺序:

Map<String, Integer> sortedMap = new LinkedHashMap<>();
unsortMap.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByKey())
    .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));

但是现在您的两个示例甚至都不是相同的底层数据结构。 TreeMap 背后有一棵树(如果我没记错的话是红黑色)。如果您希望能够以排序方式进行迭代或快速搜索键,则可以使用TreeMapLinkedHashMap 是带有一个链表的 hashmap。如果您需要维护插入顺序,例如在实现队列时,您可以使用它。

【讨论】:

    【解决方案3】:

    第二种方式不行,当你调用HashMap#put时,它不持有看跌单。你可能需要LinkedHashMap

    TreeMap 与流(LinkedHashMap):

    1. 代码风格。使用 TreeMap 更简洁,因为您可以在一行中实现它。
    2. 空间复杂度。如果原始地图是HashMap,则使用这两种方法都需要创建一个新的Map。如果原图为LinkedHashMap,则只需按照第一种方法新建一个Map即可。您可以通过第二种方法重复使用LinkedHashMap
    3. 时间复杂度。它们都应该有 O(nln(n))。

    【讨论】:

      猜你喜欢
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-09
      • 2016-08-19
      • 1970-01-01
      • 2015-10-01
      • 2013-11-03
      • 1970-01-01
      相关资源
      最近更新 更多