【问题标题】:How bad is to use Hashmaps and ArrayLists while using huge data?在使用大量数据时使用 Hashmaps 和 ArrayLists 有多糟糕?
【发布时间】:2012-01-28 08:23:56
【问题描述】:

我正在将 XML 文档读入 HashMaps、ArrayLists,以便即使在内存中也能保持关系。我的代码完成了我的工作,但我担心我在这个巨大的地图和列表上执行的迭代或函数调用。目前我正在工作的 xml 数据不是那么大。但我不知道如果有会发生什么。我需要对使用这些哈希图的逻辑执行哪些测试用例?对如此庞大的数据使用 Java 集合有多糟糕?他们有其他选择吗?海量数据会不会影响JVM崩溃?

【问题讨论】:

  • 我建议您尝试生成大而巨大的 XML 数据文件,看看会发生什么。当您了解它可以处理多大时,请尝试使用分析器来了解如何提高效率。

标签: java performance arraylist jvm hashmap


【解决方案1】:

Java 集合具有一定的开销,当它们是应用程序的主要数据结构并且有效负载数据由大量小对象组成时,这会大大增加内存使用量(极端情况下为 20 倍)。这可能导致应用程序以 OutOfMemoryError 终止,即使实际数据远小于可用内存。

  • ArrayList 实际上对于大量元素非常有效,但当您有大量空列表或仅包含一个元素时效率低下。对于这些情况,您可以使用Collections.emptyList()Collections.singletonList() 来提高效率。
  • HashMap 有同样的问题,并且存储在其中的每个元素都有相当大的开销。所以同样的建议适用于ArrayList。如果您有大量元素,可能会有更高效的替代 Map 实现,例如Google Guava
  • 当您将原始值(例如intlong)存储在集合中时,会产生最大的开销,因为需要将其包装为对象。在这些情况下,GNU Trove 集合提供了另一种选择。
  • 具体而言,问题是您是否真的需要将 XML 中的全部数据一次保存在内存中,或者是否可以将其分成小块进行处理。如果您的数据可以任意增长,这可能是最好的解决方案。
  • 最简单的短期解决方案是购买更多内存。很便宜。

【讨论】:

  • 对一个非常笼统的问题的非常彻底的回答。竖起大拇指。
【解决方案2】:

JVM 不会按照您的描述崩溃。可能发生的是 OutOfMemoryError。此外,如果您长时间保留这些集合中的数据,您可能会遇到垃圾收集问题。您真的需要将整个 XML 数据存储在内存中吗?

【讨论】:

    【解决方案3】:

    如果您正在处理临时数据并且需要快速访问它,那么您不必有很多替代方案。问题是你说“巨大”是什么意思?兆字节?千兆字节?太字节?

    虽然您的数据不超过 1G,恕我直言,将其保存在内存中可能没问题。否则,您应该考虑诸如 DB(关系或 NoSql)文件等替代方案。

    在您的具体示例中,除非您需要随机访问列表,否则我会考虑将 ArrayList 替换为 LinkedList。 ArrayList 只是数组的包装器,因此当您需要 100 万个元素时,它会分配 100 万个元素的长数组。链表更适合当元素数量很大但按索引访问元素的速率为 o(n/2) 时。如果您需要两者(即巨大的列表和快速访问),请使用TreeMap 和索引作为键。您将获得 log(n) 访问率。

    【讨论】:

    • 嗯。不好的建议。对于当前的硬件,限制应该是大约半太字节(数据和包含结构)。这就是价格合理的工作站所具备的条件。
    【解决方案4】:

    我需要对使用这些哈希图的逻辑执行哪些测试用例?

    为什么不生成大型 XML 文件(例如,比当前数据样本大 5 倍)并使用它们检查您的解析器/内存存储?因为只有您知道在您的情况下哪些文件是可能的,它们会以多快的速度增长,这是唯一的解决方案。

    对如此庞大的数据使用 Java 集合有多糟糕?有没有 他们的替代品?海量数据会不会影响JVM崩溃?

    当然,如果你尝试在内存中存储太多数据,是否可能会出现 OutOfMemory 异常,并且它不符合 GC 的条件。这个库:http://trove.starlight-systems.com/ 声明它使用更少的内存,但我自己没有使用它。可以在这里进行一些讨论:What is the most efficient Java Collections library?

    【讨论】:

      【解决方案5】:

      对如此庞大的数据使用 Java 集合有多糟糕?

      Java Map 实现和(在较小程度上)Collection 实现确实倾向于使用大量内存。当键/值/元素类型是原始类型的包装类型时,效果最为明显。

      他们有什么替代品吗?

      存在使用更少内存的原始类型“集合”的替代实现;例如GNU Trove 库。但是它们没有实现标准的 Java 集合 API,这严重限制了它们的实用性。

      如果您的集合不使用原始包装类,那么您的选择将更加有限。您也许可以实现自己的自定义数据结构以使用更少的内存,但节省的空间不会很大(以百分比计算),而且您还有大量工作要做来实现代码。

      更好的解决方案是重新设计您的应用程序,以便它不需要在内存中表示整个 XML 数据结构。 (如果你能做到这一点。)

      海量数据会不会影响JVM崩溃?

      这可能会导致 JVM 抛出 OutOfMemoryError。从技术上讲,这不是崩溃,但在您的用例中,这可能意味着应用程序别无选择,只能放弃。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-11-02
        • 2022-12-20
        • 1970-01-01
        • 1970-01-01
        • 2010-12-16
        • 2011-11-28
        • 1970-01-01
        相关资源
        最近更新 更多