Java、HashMap 和使用字符串作为键 - 字符串值是否会存储两次?

2024-04-16

如果我有一个如下所示的 HashMap:

HashMap<String, MyObject>

哪里的Stringkey 是一个字段MyObject,这个字符串值是否被存储了两次?

所以当我添加条目时:

_myMap.put(myObj.getName(), myObj);

就内存而言,我是否使用了字符串大小的两倍?还是 Java 在幕后做了一些聪明的事情?

Thanks


除非你实际上是在创建一个新的字符串值getName(),你没有重复你的内存使用。

这里有几个例子来澄清事情:

 String s1 = "Some really long string!";
 String s2 = s1;
 assert s1.equals(s2);

Here, s1 == s2;他们指的是同一个String实例。你的内存使用量是2个参考变量(没什么大不了的),1String实例,以及1 个支持char[](占用内存的部分)。


 String s1 = "Some really long string!";
 String s2 = new String(s1);
 assert s1.equals(s2);

Here, s1 != s2;他们指的是不同的String实例。但是,由于字符串是不可变的,构造函数知道它们可以共享相同的字符数组。你的内存使用量是2个参考变量,2 String实例(仍然没什么大不了的,因为......)和 1 个支持char[].


 String s1 = "Some really long string!";
 String s2 = new String(s1.toCharArray());
 assert s1.equals(s2);

在这里,就像以前一样,s1 != s2。使用了不同的构造函数,但这一次需要一个char[]反而。为了确保不变性,toCharArray() 必须归还防御副本其内部数组的值(这样对返回数组的任何更改都不会改变 String 值)。

[toCharArray() http://java.sun.com/javase/6/docs/api/java/lang/String.html#toCharArray%28%29返回]新分配的字符数组其长度是该字符串的长度,其内容被初始化为包含该字符串表示的字符序列。

更糟糕的是,构造函数还必须防御性复制给定数组到其内部支持数组,再次确保不变性。这意味着最多 3 份字符数组的数量可能同时存在于内存中!其中 1 个最终将被垃圾收集,因此您的内存使用量是 2 个引用变量,2String实例,以及2 后盾char[]! NOW你的内存使用量增加了一倍!


所以回到你的问题,只要你不创建一个新的字符串值getName()(也就是说,如果你只是简单地return this.name;),那么你就没事了。但是,如果您正在执行简单的串联(例如return this.firstName + this.lastName;), then 您的内存使用量将增加一倍!

下面的代码说明了我的观点:

public class StringTest {
    final String name;
    StringTest(String name) {
        this.name = name;
    }
    String getName() {
        return this.name;      // this one is fine!
    //  return this.name + ""; // this one causes OutOfMemoryError!
    }
    public static void main(String args[]) {
        int N = 10000000;
        String longString = new String(new char[N]);
        StringTest test = new StringTest(longString);
        String[] arr = new String[N];
        for (int i = 0; i < N; i++) {
            arr[i] = test.getName();
        }
    }
}

您应该首先验证上面的代码是否运行(java -Xmx128m StringTest)而不抛出任何异常。然后,修改getName() to return this.name + "";并再次运行它。这次你会得到一个OutOfMemoryError.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java、HashMap 和使用字符串作为键 - 字符串值是否会存储两次? 的相关文章

随机推荐