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

Java 字符串数组如何存储在内存中,java,Java,我想看看当我有很多重复的字符串时使用了多少内存。我正在使用(底部)中突出显示的方法 这里我创建了一个包含一千万个字符串的列表,其中每个字符串只有几个字符 public class Test1 { public static void main(String[] args) { int count = 10000000; List<String> names = new ArrayList<String>(); fo

我想看看当我有很多重复的字符串时使用了多少内存。我正在使用(底部)中突出显示的方法

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

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");
    }
}
公共类Test1{
公共静态void main(字符串[]args){
整数计数=10000000;
列表名称=新的ArrayList();
for(int i=0;i
我运行它,它显示88MB。我不太确定这代表什么,但我将把它作为一个数字来比较iwth

我再次做了同样的测试,只是用一些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");
    }
}
公共类Test1{
公共静态void main(字符串[]args){
整数计数=10000000;
列表名称=新的ArrayList();
for(int i=0;i
我运行这个,它再次显示88MB

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


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

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

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

您的
列表
没有存储字符串。它正在存储字符串引用

在每种情况下,你都有一个
字符串
对象,然后是一个列表,其中有许多对同一对象的引用。这就像有一栋房子,和数百万张纸,上面都有相同的地址。这占用的土地量大致相同,无论房子是平房还是豪宅

如果要查看为列表中要引用的每个条目创建不同字符串时发生的情况,请尝试:

for (int i = 0; i < count; i++) {
    names.add("test" + i);
}
for(int i=0;i
现在,您将更快地耗尽内存,因为在每次迭代中,您将创建一个新的string对象,它将占用一定的内存。确切的内存量取决于实现,但它通常是一个
string
对象,包含对
char[]
对象(字符数组)的引用,一个起始位置,一个长度和一个缓存的hashcode。因此,对于小字符串,文本数据与管理工作的开销相比显得微不足道,而对于非常大的字符串,
char[]
中的数据将占据大部分空间。

您的
列表
没有存储字符串。它存储的是字符串引用

在每种情况下,你都有一个
字符串
对象,然后是一个列表,其中有许多对同一对象的引用。这就像有一栋房子,和数百万张纸,上面都有相同的地址。这占用的土地量大致相同,无论房子是平房还是豪宅

如果要查看为列表中要引用的每个条目创建不同字符串时发生的情况,请尝试:

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

现在,您将更快地耗尽内存,因为在每次迭代中,您将创建一个新的string对象,它将占用一定的内存。确切的内存量取决于实现,但它通常是一个
string
对象,包含对
char[]
对象(字符数组)的引用,一个起始位置,一个长度,和一个缓存的hashcode。因此,对于小字符串,文本数据与管理工作的开销相比显得微不足道,而对于非常大的字符串,
char[]
将占用大部分空间。

您没有创建100万个字符串。您创建了100万个对同一个唯一字符串实例的引用。字符串文本被插入:每次代码使用时

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

如果您确实想要一百万个字符串实例,那么使用

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

这将创建一个插入字符串的副本,您将拥有100万个不同的实例。

您没有创建100万个字符串。您创建了100万个对同一个唯一字符串实例的引用。字符串文本被插入:每次代码使用时

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

如果您确实想要一百万个字符串实例,那么使用

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

这将创建一个interned字符串的副本,您将有100万个不同的实例。

这不是完全重复的,但类似于,这不是完全重复的,但类似于,我现在明白了。事实上,lorem ipsum字符串只长几百个字符,在这种情况下没有明显的区别,因为与一千万参考文献相比,这里仍然只有一个实例