String和StringBuilder之间的区别及其内部组织

时间:2011-09-01 03:47:26

标签: java string stringbuilder

这是一个非常基本的问题。我知道答案的范围是字符串是不可变的。 Stringbuilders不是,所以你可以在最后附加字符。

那么stringbuilders如何在内部组织? String是一个字符数组。

StringBuilder也是一个字符数组吗? 所以,我有一个StringBuilder MY_OBJ =“你好”。 现在,如果我尝试将字符附加到MY_OBJ的末尾,这是不是意味着您实际上正在创建一个新的数组对象并将所有这些字符复制到一个新的字符中?如果是这样,它如何比字符串更有效?

我想到的另一个问题是,如何标记StringBuilder的结尾? 就像在C中一样,我们使用“/ 0”

3 个答案:

答案 0 :(得分:8)

我不知道。我们去看看:

72   public final class StringBuilder
73       extends AbstractStringBuilder
45        * The value is used for character storage.
46        */
47       char[] value;
48   
49       /**
50        * The count is the number of characters used.
51        */
52       int count;

===

  

StringBuilder也是一个字符数组吗?

显然,在这个特定的实现中。

  

所以,我有一个StringBuilder MY_OBJ =“你好”。现在,如果我尝试将字符附加到MY_OBJ的末尾,这是不是意味着您实际上正在创建一个新的数组对象并将所有这些字符复制到一个新的字符中?

不一定。该数组不一定是完整的(count < value.length),因此可能不需要分配新数组。理想情况下,您初始化StringBuilder的容量,以便从一开始就分配足够大的数组。

StringBuilder sb = new StringBuilder(20);
sb.append("Hello");
...
sb.append(" there");
  

我想到的另一个问题是,如何标记StringBuilder的结尾?就像在C中一样,我们使用“/ 0”

你不在乎 - String/StringBuilder会在内部处理它。

答案 1 :(得分:6)

大多数StringBuilder实现来自AbstractStringBuilder,而在Sun的实现中,它是一个char数组的包装器。没有标记字符串的结尾,类本身保留一个计数变量,表示字符串的实际大小。还有一个容量方法可以告诉你真实数组有多大(以及一个trimToSize方法将字符串构建器修剪为与当前存储字符串一样大的数组)。

新数组仅在您达到当前字符串生成器容量时创建,并且此操作不是那么昂贵,因为它使用arrayCopy方法并且容量总是加倍,因此随着您的增长它变得不太可能达到限制。如果你事先知道你认为字符串构建器的大小,你也可以定义它的构造函数,这样就不必将内容复制到新数组中。

此外,此代码:

StringBuilder MY_OBJ= "Hello";

不起作用。

但是这个确实:

StringBuilder MY_OBJ= new StringBuilder("Hello");

答案 2 :(得分:1)

如果您不打算更改值,StringBuilder不会比String更有效。如果要在字符串中追加/删除字符,效率会更高。

StringBuilder的默认构造函数将创建一个可容纳16个char元素的数组。 #append(String)使用String#getChars(int, int, char[], int)将字符串的字符复制到StringBuidler的数组中。仅当没有空间添加更多字符时,才使用Arrays.copyOf(char[], int)重新调整数组大小。每次发生这种情况时,阵列的容量都会翻倍。通过计算数组中的字符数来标记结尾。

在旧版本的Java 中,当您在循环内连接字符串时,每个字符串与+运算符的连接都会创建一个新的String对象。 StringBuilder更快,因为它创建的对象更少。

如果您要继续使用StringBuilder实例,则可能需要在完成修改后调用StringBuilder#trimToSize()。它将尝试将阵列的容量降低到所需的最小值。

希望这有帮助。