Java StringBuffer如何在不创建两个对象的情况下实现append函数?
这是一个面试问题。我被要求实现Java StringBuffer如何在不创建两个对象的情况下实现append函数?,java,string,stringbuilder,Java,String,Stringbuilder,这是一个面试问题。我被要求实现StringBufferappend函数。面试后我看到了密码。但我无法理解如何通过创建单个对象来完成操作 我是这样想的 String s = "orange"; s.append("apple"); 这里创建了两个对象 但是 现在这里只创建了一个对象 Java是如何执行此操作的?这是您的朋友,Luke 以下是字符串的源代码是不可变的。追加字符串只能生成新字符串 StringBuilder是可变的。附加到StringBuilder是一个就地操作,就像添加到Array
StringBuffer
append函数。面试后我看到了密码。但我无法理解如何通过创建单个对象来完成操作
我是这样想的
String s = "orange";
s.append("apple");
这里创建了两个对象
但是
现在这里只创建了一个对象
Java是如何执行此操作的?这是您的朋友,Luke
以下是字符串的源代码
是不可变的。追加字符串只能生成新字符串
StringBuilder
是可变的。附加到StringBuilder
是一个就地操作,就像添加到ArrayList一样。StringBuffer,就像StringBuilder分配一个字符数组,它将附加的字符串复制到该数组中。仅当字符数超过数组大小时,它才会创建新对象,在这种情况下,它会重新分配和复制数组。StringBuilder
在char[]中保留char
s的缓冲区
并在调用toString
时将它们转换为字符串。首先,您的问题有一个问题:
String s = "orange";
s.append("apple");
这里创建了两个对象
正确,在StringBuffer/StringBuilder中创建了两个对象,字符串“orange”和字符串“apple”,如果不溢出缓冲区,则不会创建任何对象。因此,这些代码行创建2或3个对象
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
现在这里只创建了一个对象
我不知道你从哪里得到的,在这里你创建了一个StringBuilder对象,一个“橙色”字符串,一个“苹果”字符串,总共3个对象,或者如果我们溢出了StringBuilder缓冲区,就创建了4个。(我将数组创建计算为对象创建)
我将您的问题理解为,StringBuilder如何在不创建新对象的情况下进行追加(当缓冲区没有溢出时)
您应该看看StringBuilder
,因为它是非线程安全的实现。代码有趣且易于阅读。我已经添加了内联注释
作为内部结构,有一个字符数组,而不是字符串。它最初的长度为16,每次超过容量时都会增加。如果要附加的字符串适合char数组,则无需创建新对象
StringBuilder
extends,您可以在其中找到以下代码:
/**
* 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
}
(int-srcbegen,int-srcEnd,char[]dst,int-dstbegen)将此字符串中的字符复制到目标字符数组中
因此,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);
}
void expandCapacity(int最小容量){
//获取当前长度加一并加倍
int newCapacity=(value.length+1)*2;
if(newCapacity<0){//如果我们有一个整数溢出
newCapacity=Integer.MAX_VALUE;//只需使用最大正整数
}否则如果(minimumCapacity>newCapacity){//,是否足够?
//如果加倍还不够,请使用计算的实际长度
新容量=最小容量;
}
//将旧值复制到新数组中
value=Arrays.copyOf(value,newCapacity);
}
(char[]original,int newLength)复制指定的数组,截断或填充空字符(如有必要),使副本具有指定的长度
在我们的例子中,填充,因为我们正在扩展长度。这不会编译
String S= "orange";
S.append("apple");
如果你这样做
final String S= "orange";
final S2 = S + "apple";
这不会创建任何对象,因为它在编译时优化为两个字符串文本
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
这将创建两个对象StringBuilder
和它包装的char[]
。如果你使用
String s2 = s.toString();
这将再创建两个对象
如果你这样做
String S= "orange";
S2 = S + "apple";
这和
String S2 = new StringBuilder("orange").append("apple").toString();
它创建2+2=4个对象。正如其他描述的那样,StringBuffer
是可变的,它是通过使用char
数组实现的。StringBuffer
中的操作是就地操作
更多信息可从以下链接获得
它显示了使用char
数组的简单StringBuffer实现
String s = "orange";
s.append("apple");
这是不正确的,因为追加方法在字符串中不可用:tl;dr:简单地说,每个使用+
字符的字符串连接表达式都会导致一个新的字符串对象,并将初始字符串的内容复制到新对象中StringBuffer
保存一个内部结构,该结构仅在需要时扩展,并将字符附加到其中
****String s1="Azad"; ----One object will create in String cons. pool
System.out.println(s1);--output--Azad
s1=s1.concat("Raja"); Two object will create 1-Raja,2-AzadRaja and address of AzadRaja Store in reference s1 and cancel ref.of Azad object
System.out.println(s1); --output AzadRaja****
嘿,但是很多人使用+
字符串连接强>
嗯,我们/他们不应该
在内存使用方面,您正在使用StringBuffer
中的数组来保存字符-这会调整大小,但如果在调整大小时应用的算法是有效的,则很少会这样做,并且只调用一个String
对象,该对象创建一次toString()
,比在每个+
串联上创建新的字符串
对象要好得多
就时间复杂度而言,字符仅从\u chars
复制一次到新字符串(O(n)
时间复杂度),这通常必须优于使用+
运算符的字符串串联,在该运算符上,每次操作都会将字符的新副本复制到新对象,从而导致O(1+2+..+n)=O(n^2)
操作
我应该自己实施一个吗?
这在练习方面对您有好处,但现代语言提供了本机StringBuffer
实现,以便在生产代码中使用它
四个sim卡
****String s1="Azad"; ----One object will create in String cons. pool
System.out.println(s1);--output--Azad
s1=s1.concat("Raja"); Two object will create 1-Raja,2-AzadRaja and address of AzadRaja Store in reference s1 and cancel ref.of Azad object
System.out.println(s1); --output AzadRaja****
public String toString() {
return new String(_chars);
}