映射清除vs null

时间:2013-10-24 01:13:17

标签: java map hashmap

我有一张地图用于存储动态数据,这些数据一旦被创建就被丢弃(即使用;它们被快速消耗)。它响应用户交互,因为当用户点击按钮时,地图被填充,然后数据用于做一些工作,然后不再需要地图。

所以我的问题是什么是更好的清空地图的方法?我应该每次都设置为null还是应该拨打clear()?我知道清楚是线性的。但我不知道如何将这个成本与每次创建地图的成本进行比较。地图的大小不是恒定的,因为它可能在创作之间从n到3n元素运行。

6 个答案:

答案 0 :(得分:8)

如果没有从其他可能难以设置新对象的对象引用地图,只需null - 从旧地图开始并从头开始可能比调用{{1因为不需要进行线性时间清理。由于现代系统上的垃圾收集成本很小,因此很有可能以这种方式节省一些CPU周期。您可以通过指定初始容量来避免多次调整地图大小。

首选clear()的一种情况是在系统中的多个对象之间共享地图对象时。例如,如果您创建一个地图,将其提供给多个对象,然后在其中保留一些共享信息,则在所有这些对象中将地图设置为新地图可能需要保留对具有地图的对象的引用。在这种情况下,更容易在同一个共享地图对象上调用clear()

答案 1 :(得分:2)

嗯,这取决于你可以投入多少内存。如果你有很多,那没关系。但是,将映射本身设置为null意味着您已释放垃圾收集器 - 如果只有映射具有对其内部实例的引用,则垃圾收集器不仅可以收集映射,还可以收集其中的任何实例。 Clear确实清空了地图,但它必须迭代地图中的所有内容以将每个引用设置为null,这发生在您可以控制的执行时间内 - 垃圾收集器基本上必须执行此工作,所以让它做它的东西。请注意,将其设置为null不会让您重复使用它。重用地图变量的典型模式可能是:

Map<String, String> whatever = new HashMap<String, String();
// .. do something with map
whatever = new HashMap<String, String>();

这允许您重用变量而不将其设置为null,您可以静默地丢弃对旧映射的引用。这在非内存管理应用程序中是非常糟糕的做法,因为它们必须引用旧指针来清除它(这是其他语言中的悬空指针),但是在Java中,因为没有引用它,所以GC将其标记为有资格进行收集。

答案 2 :(得分:0)

我认为现有地图的归零比clear()便宜。由于在现代JVM中对象的创建非常便宜。

答案 3 :(得分:0)

简短回答:使用Collection.clear(),除非它过于复杂,无法保持collection arround。

详细解答:在Java中,内存的分配几乎是即时的。它比在VM内部移动的指针更轻松。但是,这些对象的初始化可能会增加一些重要的东西。此外,使用内部缓冲区的所有对象都可以调整其内容的大小和复制。使用clear()确保缓冲区最终稳定到某个维度,以便重新分配内存并将旧缓冲区复制到新缓冲区永远不会是必需的。

另一个重要问题是重新分配然后释放大量对象将需要更频繁地执行垃圾收集器,这可能会导致突然滞后。

答案 4 :(得分:0)

如果你总是拿着地图,它会被提示给老一代。如果每个用户具有一个对应的地图,则旧一代中的地图数量与用户的数量成比例。当用户数量增加时,它可能会更频繁地触发Full GC。

答案 5 :(得分:0)

您可以同时使用两者。

之前的一个答案指出clear预计会在成熟的地图实施中花费一些时间。在不检查HashMapTreeMapConcurrentHashMap之类的源代码的情况下,我希望他们的clear方法能够获得恒定时间,加上amortized垃圾回收成本。

另一张海报指出共享地图无法取消。好吧,如果你想要它,它可以通过使用proxy对象来实现它,该对象封装了一个正确的映射并在需要时将其清空。当然,您必须自己实现代理地图类。

Map<Foo, Bar> myMap = new ProxyMap<Foo, Bar>();
    // Internally, the above object holds a reference to a proper map,
    // for example, a hash map. Furthermore, this delegates all calls
    // to the underlying map. A true proxy.
myMap.clear();
    // The clear method simply reinitializes the underlying map.

除非你做了类似上述的事情,否则clear和nulling在重要的方面是相同的,但我认为假设你的地图即使目前没有共享也可能变得更加成熟由于你无法预见的力量,以后分享。

clear还有另一个原因而不是归零,即使地图未共享也是如此。您的地图可以由外部客户端实例化,例如factory,因此如果您通过清空地图清除地图,您可能会不必要地自己coupling到工厂。为什么清除地图的对象必须知道你使用番石榴Maps.newHashMap()实例化你的地图,上帝知道什么参数?即使这不是您项目中的现实问题,但仍然需要让自己与成熟的实践保持一致。

由于上述原因,在其他条件相同的情况下,我会投票给clear

HTH。