【问题标题】:Map.clear() vs new Map : Which one will be better? [duplicate]Map.clear() 与 new Map :哪个更好? [复制]
【发布时间】:2011-10-09 03:05:35
【问题描述】:

我有一个 Map 作为 Map<String, String> testMap = new HashMap<String, String>(); 的语法。 在这张地图中可以有 1000 个数据。

当我的应用程序需要新的数据列表时,我必须清除地图。但是当我看到 Map.clear() 的代码为

/**
     * Removes all of the mappings from this map.
     * The map will be empty after this call returns.
     */
    public void clear() {
        modCount++;
        Entry[] tab = table;
        for (int i = 0; i < tab.length; i++)
            tab[i] = null;
        size = 0;
    }

我意识到 clear 方法会循环 n 次(其中 n 是 Map 中的数据数)。所以我认为有一种方法可以将该地图重新定义为testMap = new HashMap&lt;String, String&gt;(); 并且以前使用过的地图将被垃圾收集。

但我不确定这是否是一个好方法。我正在开发移动应用程序。

你能指导我吗?

【问题讨论】:

  • 这个问题已经发布很久了,但无论如何,谷歌会继续引导我们解决这个问题。因此,使用 clear 而不是 new 的另一个优势。您将能够将映射声明为最终映射,因此编译器将能够免费检测编程错误。对于其他类型的结构,“final”也将消除分配新内存的负担,使我们的代码(更快)更快。

标签: java android performance collections


【解决方案1】:

将删除所有数据的 map.clear()。请注意,这只会丢弃所有条目,但会保持用于存储条目的内部数组大小相同(而不是缩小到初始容量)。如果您还需要消除它,最简单的方法是丢弃整个 HashMap 并用新实例替换它。当然,这只有在您控制谁拥有指向地图的指针时才有效。

至于回收内存,你将不得不让垃圾收集器完成它的工作。

你的价值观也很长吗?在这种情况下,您可能希望查看比通用 HashMap 更(内存)高效的实现,例如在GNU Trove library 中找到的 TLongLongHashMap。这应该会节省很多内存。

【讨论】:

    【解决方案2】:

    具有 clear() 方法的想法是从映射中删除对其他对象的引用,这样如果“映射在其他地方被引用”,键/值就不会被 gcing 阻止。

    但是,如果您的地图是仅由您的特定代码使用的本地地图(即“地图未在其他地方引用”),那么请继续使用新地图,但将 1000 引用设置为 null 不会是无论如何,性能受到很大影响。

    【讨论】:

    • 是的,对于 1000 次引用,这不会对性能造成很大影响。我在问创建一个新实例是否比 clear 方法更好。使用新实例有什么缺点吗?
    • 主要缺点是新的,你的旧 HashMap 仍然在内存中,直到垃圾收集器释放它。它会增加一点内存的内存开销和更多的处理开销供 GC 释放它。在任何情况下,任何一个选项(重用或创建新)的差异都可以忽略不计(除非您的应用所做的只是创建 HashMap)
    【解决方案3】:

    我认为调用 new HashMap() 是一个更好的主意,因为它不需要像清除 hashmap 那样做太多的处理。此外,通过创建新的 hashmap,您消除了 hashmap 仍可能绑定到使用数据的控件的可能性,这会在清除 hashmap 时导致问题。

    【讨论】:

      【解决方案4】:

      我认为在 java 中创建对象在内存方面更昂贵,所以你最好使用.clear(),所以你使用相同的对象而不是创建新的对象

      【讨论】:

        【解决方案5】:

        复杂的问题。让我们看看会发生什么。

        您实例化一个新实例,该实例由新数组支持。因此,垃圾收集器应该清除之前映射中的所有键和值,并清除对自身的引用。所以 O(n) 算法无论如何都会执行,但是在垃圾收集器线程中。对于 1000 条记录,您不会看到任何差异。 但。性能guide 告诉您最好不要创建新对象,如果可以的话。所以我会使用clear() 方法。

        无论如何,尝试两种变体并尝试测量。始终测量!

        【讨论】:

        • +1 阅读指南后,我意识到自己的困惑所在。谢谢。
        • 查看我对@Tanveer 回答的评论。您无法估算 GC 的成本。
        【解决方案6】:

        不要忘记重新填充地图

        如果您没有在新地图上指定容量,您将在新创建的地图上获得相当多的开销,因为重新哈希(每个都是 O(n)(当时)并且发生 O(log( n)) 次,虽然这可能会摊销到 O(n) 总数,但如果它们一开始没有发生,你仍然会更好)

        这不会发生在已清除的地图上,因为容量不会改变

        【讨论】:

          【解决方案7】:

          当您在大小为 n... 的 Map 上说 Map.clear() 时,您是在要求 GC 清理 2*n(键和值)对象。当您对同一个 Map 说 null 时,您是在要求 GC 清理 2*n+1(1 表示 Map 本身)对象。然后,您将不得不创建一个新的 Map 实例,这又是一个开销。所以去Map.clear()。您最好在实例化地图时预设地图的大小。

          【讨论】:

          • 您给出的大 O 估计值仅适用于未在其他任何地方引用 Map 中的键和值的情况。如果在应用程序的其他地方引用了任何键和值,那么它们将不会被垃圾收集。如果“清理”是指垃圾收集器必须检查对象以查看它是否需要垃圾收集,我可能会误会。这里还有一点......即使没有对它们的引用,垃圾收集器也可能永远清理对象:stackoverflow.com/a/2506525/361855。我的观点是,更改地图参考时您无法估计 GC 的成本。
          猜你喜欢
          • 2012-07-07
          • 1970-01-01
          • 2014-10-14
          • 2013-07-05
          • 2018-04-15
          • 1970-01-01
          • 2014-03-21
          • 1970-01-01
          相关资源
          最近更新 更多