如何优化代码以始终使用对字符串的相同引用而不增加内存使用量



我正在开发一个有很多重复字符串的应用程序,我的任务是消除它们以减少内存使用量。我的第一个想法是使用 String.intern 来保证只有一个字符串引用存在。它有效地减少了堆内存,但它增加了太多的 PermGen;事实上,由于有许多字符串只声明一次,因此应用程序使用的内存总量实际上增加了。

在搜索了另一个想法之后,我找到了这种方法:https://stackoverflow.com/a/725822/1384913。

它与 String.intern 发生了同样的事情:字符串使用量减少了,但我保存的内存正在WeakHashMapWeakHashMap$Entry类中使用。

有没有一种有效的方法可以为每个字符串维护一个引用,该字符串不会花费与我正在恢复的相同数量的内存?

我找到了WeakHashMap的替代方案:Eclipse JDT库提供的WeakHashSet。它的行为与WeakHashMap相同,但占用的内存更少。此外,您只需要调用该方法add,如果 String 尚不存在,它将在集合中添加 String,否则返回现有的字符串。

我唯一不喜欢的是它不使用泛型,迫使开发人员强制转换对象。我的intern方法非常简单,如您在下面看到的:

WeakHashSet声明 :

private static WeakHashSet stringPool = new WeakHashSet(30000); //30 thousand is the average number of Strings that the application keeps.

和实习方法:

public static String intern(String value) {
    if(value == null) {
        return null;
    }
    return (String) stringPool.add(value);
}

为什么不使用 StringBuilder/StringBuffer 类而不是 String。使用此类的实例,您始终可以使用具有不同值的同一实例。- 安库尔

在类似的情况下,只要有可能,我就将字符串常量重构为枚举。这样,您将获得两个好处:

  • 枚举实例是单例实例,因此不会遇到内存问题
  • 使用字符串时没有拼写错误。

缺点:

  • 大量的工作,犯错误的可能性有无限,如果你没有足够的测试用例
  • 有时这并非微不足道,例如,当您必须与第三方库交互时,您不能只是编辑......
  • 如果这些是运行时确定的,而不是编译时,那么简直是不行的......

最新更新