我有一个使用大量String
对象的应用程序。我的一个对象(我们称之为Person
(包含其中的 9 个。写入每个String
对象的数据永远不会写入多次,但会在之后多次读取。在给定的时间,将有几十万个左右的Person
对象,其中许多Person
对象将共享名字,姓氏等。
我正在尝试想一些直接的方法来减少Person
对象消耗的内存量,但是当涉及到Java如何管理其下面的内存时,我不是专家。
在我进入这个兔子洞之前,我想知道如果我沿着这些道路走下去会有什么缺点,以及它是否首先有意义:
- 使用
StringBuilder
或StringBuffer
仅仅是因为trimToSize()
方法允许我减少字符串中使用的分配字节数。 - 将字符串存储为数组
byte[]
并提供一个将byte[]
转换为String
的 getter 和一个接受String
并转换为byte[]
的 setter - 数据正在被读取很多,所以这会不会太贵了?
为 - (让我们说("名称"创建一个哈希表,以防止一遍又一遍地为同一名称重复分配(使用指针((可能有数千个名称具有 10+ 个字符(。
在我毫无意义地走上这些道路之前,这样做有意义吗?也许Java已经在减少String
分配并检查重复项?
我也不介意好好读一读。我找到了一些文档,但没有深入探讨的内容。
-
显然,在这种情况下,StringBuilder和StringBuffer无法提供帮助。字符串是不可变的对象,因此引入这两个类是为了构建字符串而不是用于存储。无论如何,如果您连接/在中间插入字符/从字符串中删除一些字符,您可以(在大多数情况下 - 必须(使用 StringBuilder
-
在我看来,第二个选项可能会导致内存消耗增加,因为每次您需要 byte[] 时都会创建新的字符串。
-
手写的StringDeduplicator是非常合理的解决方案,特别是如果你坚持使用java 5,6,7。
-
Java 8/9 具有字符串重复数据删除选项。默认情况下,此选项处于禁用状态。要在 Java 8 中使用这个垃圾回收器,您必须启用 G1 垃圾回收器,而在 Java 9 中,G1 是默认的。
-XX:+使用字符串重复数据删除
有关字符串重复数据删除,请参阅:
- JEP 192:G1 中的字符串重复数据删除
- Java 8 更新 20 发行说明
- 其他堆栈溢出帖子