java - StringBuffer 如何在不创建两个对象的情况下实现 append 功能?

标签 java string stringbuilder

这是一个面试问题。我被要求实现 StringBuffer 附加功能。面试后看到了代码。但我无法理解如何通过创建单个对象来完成操作。

我是这样想的。

String s = "orange";
s.append("apple");

这里创建了两个对象。

但是

StringBuilder s = new StringBuilder("Orange");
s.append("apple");

现在这里只创建了一个对象。

Java 是如何进行这个操作的?

最佳答案

首先你的问题有问题:

String s = "orange";
s.append("apple");

here two objects are created

正确,创建了两个对象,字符串“orange”和字符串“apple”,在 StringBuffer/StringBuilder 中,如果我们不溢出缓冲区,则不会创建任何对象。所以这些代码行创建了 2 或 3 个对象。

StringBuilder s = new StringBuilder("Orange");
s.append("apple");

Now here only one object is created

我不知道你从哪里得到的,在这里你创建一个 StringBuilder 对象,一个“橙色”字符串,一个“苹果”字符串,总共 3 个对象,如果我们溢出 StringBuilder 缓冲区,则创建 4 个。 (我把数组的创建算作对象的创建)。


我将您的问题读为,StringBuilder 如何在不创建新对象的情况下进行追加(当缓冲区未溢出时)?

您应该查看 StringBuilder,因为它是非线程安全的实现。该代码很有趣且易于阅读。我已经添加了内联注释。

作为内部结构,有一个字符数组,而不是字符串。它最初是用长度 16 build 的,每次超过容量时都会增加。如果要追加的字符串适合 char 数组,则无需创建新对象。

StringBuilder 扩展 AbstractStringBuilder ,您将在其中找到以下代码:

/**
 * The value is used for character storage.
 */
char value[];

由于并非所有数组都会在给定时间使用,另一个重要的变量是长度:

/**  
 * The count is the number of characters used.
 */
int count;

append的重载有很多,但最有趣的是以下:

public AbstractStringBuilder append(String str) {
    if (str == null) str = "null"; //will literally append "null" in case of null
    int len = str.length(); //get the string length
    if (len == 0) return this; //if it's zero, I'm done
    int newCount = count + len; //tentative new length
    if (newCount > value.length) //would the new length fit?
        expandCapacity(newCount); //oops, no, resize my array
    str.getChars(0, len, value, count); //now it will fit, copy the chars 
    count = newCount; //update the count
    return this; //return a reference to myself to allow chaining
}

String.getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) Copies characters from this string into the destination character array.

所以,append 方法很简单,唯一需要发现的魔法就是 expandCapacity,这里是:

void expandCapacity(int minimumCapacity) {
    //get the current length add one and double it
    int newCapacity = (value.length + 1) * 2; 
    if (newCapacity < 0) { //if we had an integer overflow
        newCapacity = Integer.MAX_VALUE; //just use the max positive integer
    } else if (minimumCapacity > newCapacity) { //is it enough?
        //if doubling wasn't enough, use the actual length computed
        newCapacity = minimumCapacity;
    }
    //copy the old value in the new array
    value = Arrays.copyOf(value, newCapacity); 
}

Arrays.copyOf(char[] original, int newLength) Copies the specified array, truncating or padding with null characters (if necessary) so the copy has the specified length.

在我们的例子中,填充,因为我们正在扩展长度。

关于java - StringBuffer 如何在不创建两个对象的情况下实现 append 功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8011338/

相关文章:

java - 如何使用 JNI android 获取应用程序构建配置(调试或发布)?

c++ - 使用统一初始化时未调用 std::string(count, ch)

c# - 是否需要在替换 StringBuilder 中的字符串之前进行检查(使用 "Contains"或 "IndexOf"等函数)?

java - XPage:通过 SSJS 和 Java 保存文档时发生文档冲突

java - MongoDB聚合Java API不返回结果

Javascript - 如何连接两个不同大小的数组中的字符串值?

.net - StringBuilder 的 RAM 消耗情况如何?

java - Base64 值导致 SAX 解析器中的 StringBuilder.append 内存不足错误

java - 在java中,如果你第二次调用同一个函数,程序 "remember"会是结果吗?

javascript - 插入数字字符串