对于JVM的字符串池,在Java中创建String的时间成本是多少?

时间:2013-11-11 12:49:12

标签: java string jvm

Java有一个字符串池,因此在实际创建一个新字符串之前我想有一个检查是否已存在相同的字符串,这次调用的成本是多少?

池是基于散列或树的结构吗?

在任何一种情况下,我都猜到了String哈希码的性能,因为搜索树使用哈希码作为密钥?

我猜它是关于log n的,其中n是当前堆上的字符串数。

6 个答案:

答案 0 :(得分:7)

来自this unofficial blog

  

Java虚拟机维护内部字符串(唯一字符串池)的内部引用列表,以避免堆内存中重复的String对象。只要JVM从类文件加载String文本并执行,它就会检查该String是否存在于内部列表中。如果它已存在于列表中,则它不会创建新的String,而是使用对现有String对象的引用。

     

JVM在内部对String字符进行此类检查,但不对通过“new”关键字创建的String对象进行检查。您可以显式强制JVM对使用new方法通过“String.intern()”关键字创建的String对象执行此类检查。这会强制JVM检查内部列表并使用现有的String对象(如果已存在)。

答案 1 :(得分:0)

没有检查字符串池中是否已存在新字符串,这是您不应使用==来比较字符串的原因之一。

字符串池用于编译时已知的字符串。或者,如果您手动使用intern()并使用返回的实例。

答案 2 :(得分:0)

每次在运行时动态创建String时,都会返回一个新的String实例。字符串池只包含字符串文字和字符串编译时常量,或通过调用String.intern()明确地添加到池中的字符串。

答案 3 :(得分:0)

任何可以在编译时被知道的String都是池,这意味着以下只创建一个字符串。 (字符串文字是最明显的例子,但任何编译时常量字符串都是合并的)

static final String a= "hello world";
static final String b= "hello world";
static final String c= "hello" + " world";

但是,在程序的正常运行期间创建的任何字符串都不会被合并,因此除非您明确地调用.intern()

,否则不会进行此类检查

答案 4 :(得分:0)

当JVM运行时,只有常量字符串(即硬编码)在字符串池中。

public class StringExample{
    private static final String CONSTANT = "Cannon Ball!!!"; // <- In the pool
    public void processStrings(String[] args){
                               //        ^--Assumed contents are variables, not in the pool
        String temp = "I'll wade in."; // <- In the pool
        StringBuilder sb = new StringBuilder(100);
        sb.append("I").append(" hate").append(" water.");  
        String dynamic = sb.toString(); //  <- Not in the pool.
        dynamic.intern(); // <- Now it's in the pool.

    }
}

所有动态字符串都在String池外部。您可以通过调用String.intern()以编程方式将字符串添加到池中。

<小时/> 编辑:解决您对问题的评论:如果您有以下内容:

public class StringExample{
   public static final String CONSTANT = "Just me.";
}
public class Foo{
   private String value = StringExample.CONSTANT;
}

在编译时,编译器只是用硬编码字符串替换引用,因此它等同于执行

public class StringExample{
   public static final String CONSTANT = "Just me.";
}
public class Foo{
   private String value = "Just me.";
}

答案 5 :(得分:0)

  

Java有一个字符串池,因此在实际创建一个新字符串之前我想有一个检查是否已存在相同的字符串,这次调用的成本是多少?

这仅适用于String文字,而不是您创建的字符串。您可以调用String.intern()将其添加到池中,但只能在创建它之后。

  

池是基于散列或树的结构吗?

它是一个固定大小的哈希映射,带有用于冲突的链表。我建议你不要过度使用它。因为它不能扩展。

  

在任何一种情况下,我都会想到String哈希码的性能,因为搜索树使用哈希码作为密钥?

如果您需要字符串池,我建议您自己编写一个。我有一个使用byte[]CharSequence这样的StringBuilder并汇集字符串,因此它不会在90%的时间内创建对象(即目标)

  

我猜它是关于log n的,其中n是当前堆上的字符串数。

实际上O(1)高达10,000左右就是容量,之后是O(n)并不是很好。

  

如何汇总/缓存文字,编译器是否用对静态的引用替换文字? -

编译器在给定的类文件中组合了字符串文字,但JVM接受了它并将它们组合到整个JVM中。