【问题标题】:how to optimize memory usage for a big memory?如何优化大内存的内存使用?
【发布时间】:2026-01-31 05:15:01
【问题描述】:

我在 java 中有一个很大的 HashMap,用于存储从 String 到 Integer 的映射。它有 40 万条记录。它运行正常,但我想知道在内存使用方面是否有更好的优化。 Map初始化后,只会搜索,没有其他更新操作。

我依稀记得我遇到了一些将字符串键转换为 int 的建议,但不确定。请对此提供帮助或分享您的想法。

谢谢。

【问题讨论】:

  • 为什么不使用数据库?甚至嵌入?
  • 您的密钥代表什么数据?即名称、字典中的单词、文件系统路径、IP 地址等。
  • 英文单词。谢谢。
  • 字符串长度是多少???后续搜索是否总是成功?

标签: java performance memory optimization map


【解决方案1】:

我依稀记得我遇到了一些将字符串键转换为 int 的建议,但不确定。

如果字符串键实际上是整数的字符串表示,那么将它们转换为IntegerLong 对象......使用Integer.valueOf(String) 可能是有意义的。您将节省一些内存,因为原始包装类使用的内存少于相应的String 对象。节省的空间可能很显着(可能是 ~16 字节,而每个键约 40 字节......取决于你的平台。)

另一方面,您需要在进行 hashmap 查找之前将候选键从 String 转换为真正的键类型。这种转换需要一些时间,并且通常会产生一些垃圾。


但如果String 键不代表整数,那么这根本行不通。 (或者至少......我不知道你指的是什么“转换”......)

另请注意,密钥类型必须是 Integer / Long 而不是 int / long。泛型类型参数必须是引用类型。


可能有 3rd-party 集合实现也会有所帮助...取决于您的数据结构的工作原理;例如Trove,番石榴,Fastutil。然后尝试与 String -> Integer preconversion 结合...


关于使用数据库的建议。如果

  • 您不需要数据库的查询/更新/事务功能,并且
  • 您可以负担得起将数据保存在内存中的内存,并且
  • 您可以负担将数据加载到内存中的启动成本,

那么使用数据库只会对每次查找造成很大的、不必要的性能影响。

【讨论】:

    【解决方案2】:

    如果数据太大,将数据写入数据库最终是最好的解决方案,但 400k 在内存中仍然可行。

    但是,Java 的内置 HashMap 实现使用单独的链接,并且每个键值对都有一个单独的类。通过构建Map 的二次探测实现,我获得了极大 (30%) 的速度提升和惊人的 (50%) 内存提升。

    我建议你在互联网上四处搜索。周围有很多很好的实现!

    【讨论】:

    • 很高兴知道。谢谢。你知道任何好的资源指针吗?
    【解决方案3】:

    您可以使用Guava'sImmutableMap——它针对一次性数据进行了优化,并采用~15% less memory than HashMap

    【讨论】:

      【解决方案4】:

      如果你想以更高的速度读取,你可能想要调整 initialCapacityloadFactor 也改进 hashCode() 以避免冲突,如果你有太多的写入,你可能想要对 hashCode() 进行基准测试,

      即使这对您的应用程序来说太大了,您也可能需要考虑将其从 jvm 移出到某个缓存 (redis),或者如果您能承受一点读/写延迟,也可以是数据库

      【讨论】:

      • 以String为key,是否还有进一步优化hashCode()的空间?我认为默认会是最好的。在 initialCapacity 方面,也许我可以只使用 400K 的地图大小作为容量,这样就不会浪费内存,因为我知道不会添加新条目。这听起来合理吗?