如何将字符串数组存储在内存中

时间:2014-02-10 22:09:46

标签: java

当我有很多重复的字符串时,我试图查看使用了多少内存。我正在使用this answer中突出显示的方法(位于底部)

我在这里创建了一个包含一千万个字符串的列表,其中每个字符串只有几个字符。

public class Test1 {

    public static void main(String[] args) {
        int count = 10000000;
        List<String> names = new ArrayList<String>();
        for (int i = 0; i < count; i++) {
            names.add("test");
        }
        Runtime rt = Runtime.getRuntime();
        long usedMem = rt.totalMemory() - rt.freeMemory();
        System.out.println(usedMem / (1024*1024) + " MB");
    }
}

我运行它,它说88 MB。我不太清楚这代表什么,但我只是把它作为一个数字进行比较。

我再次进行相同的测试,除了用一些lorem ipsum文本替换小字符串

public class Test1 {

    public static void main(String[] args) {
        int count = 10000000;
        List<String> names = new ArrayList<String>();
        for (int i = 0; i < count; i++) {
            names.add("Lorem ipsum dolor sit amet, brute euismod eleifend te quo, ne qui iudicabit hendrerit. Ea sit dolore assentior prodesset. In ludus adipiscing eos, ius erat graeco at, cu nec melius copiosae. Epicuri suavitate gubergren id sea, possim animal eu nam, cu error libris expetendis his. Te sea agam fabulas, vis eruditi complectitur ei. Ei sale modus vis, pri et iracundia temporibus. Mel mundi antiopam ad.");
        }
        Runtime rt = Runtime.getRuntime();
        long usedMem = rt.totalMemory() - rt.freeMemory();
        System.out.println(usedMem / (1024*1024) + " MB");
    }
}

我运行它,它再次说88 MB。

这并不意味着要正确地对内存使用情况进行基准测试,但我希望ipsum lorem字符串的数量要大一些,因为字符串中的字符大约是50倍。

Java如何在内存中存储字符串数组?或者,我做错了什么?

3 个答案:

答案 0 :(得分:5)

您的List<String>没有存储字符串。它存储字符串引用

在每种情况下,您都有一个String对象,然后是一个包含大量对同一对象的引用的列表。这就像拥有一个房子,数百万张纸都有相同的地址。无论房屋是平房还是豪宅,都需要大致相同数量的土地。

如果您想查看为列表中的每个条目创建不同的字符串时会发生什么,请尝试:

for (int i = 0; i < count; i++) {
    names.add("test" + i);
}

现在你的内存耗尽得更快,因为每次迭代你都会创建一个新的字符串对象,这会占用一定的内存。 精确内存量取决于实现,但它通常是一个String对象,包含对char[]对象(一个字符数组)的引用,一个起始位置,一个长度和缓存的哈希码。因此,对于小字符串,文本数据与内务工作的开销相比相形见绌,而对于非常大的字符串,char[]中的数据将占用大部分空间。

答案 1 :(得分:5)

您没有创建100万个字符串。您创建了100万个对同一个唯一String实例的引用。字符串文字是实习的:每次代码使用

String s = "hello";

它使用放置在池中的字符串“hello”。如果85个类声明了这样一个变量,它们都将在池中引用同一个String。

如果您真的想要100万个String实例,请使用

list.add(new String("..."));

这将制作实习字符串的副本,并且您将拥有100万个不同的实例。

答案 2 :(得分:3)

Java使用字符串池。这意味着当您多次使用相同的字符串时,它们实际上指向同一个实例。