大家好,又见面了,我是你们的朋友全栈君。
一、前言
我们在实际的开发中,如果需要进行字符串的频繁拼接,会出现以下问题:
java中的字符串是不可变的,每一次拼接都会产生新字符串。 这样会占用大量的方法区内存。造成内存空间的浪费。
eg.
代码语言:javascript复制String s = "abc";
s = "hello";
就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象:
代码语言:javascript复制"abc"
"hello"
"abchello"
因此引出StringBuffer和StringBuilder可变字符串!
二、如何优化StringBuffer和StringBuilder的性能?
在创建StringBuffer和StringBuilder的时候尽可能给定一个初始化容量。
最好减少底层数组的扩容次数。预估计一下,给一个大一些初始化容量。
关键点:给一个合适的初始化容量。可以提高程序的执行效率。
三、StringBuffer和StringBuilder的区别?
StringBuffer中的方法都有:synchronized
关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
StringBuilder中的方法都没有:synchronized
关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。
- StringBuffer是线程安全的。
- StringBuilder是非线程安全的。
四、String为什么是不可变的?
源代码内,String类中有一个 byte[ ] 数组,这个byte[ ]数组采用了 final
修饰,
因为数组一旦创建长度不可变。并且被final修饰的引用一旦指向某个对象之后,不可再指向其它对象,所以String是不可变的!
所以”abc” 无法变成 “abcd”
五、StringBuilder和StringBuffer为什么是可变的呢?
源代码内,StringBuffer和StringBuilder内部实际上是一个 byte[ ]数组,这个byte[]数组没有被final修饰,
StringBuffer和StringBuilder的初始化容量是 16
,当存满之后会进行扩容,底层调用了数组拷贝的方法System.arraycopy()。所以StringBuilder和StringBuffer适合于使用字符串的频繁拼接操作。
注意: StringBuffer和StringBuilder默认初始化容量为16个byte[] 数组
总结
- StringBuffer/StringBuilder可以看做
可变长度字符串
。 - StringBuffer/StringBuilder初始化容量
16
. - StringBuffer/StringBuilder是完成字符串拼接操作的,方法名:
append
- StringBuffer是线程安全的。StringBuilder是非线程安全的。
- 频繁进行字符串拼接不建议使用“ ”
六、构造方法
构造方法名 |
---|
StringBuilder() |
StringBuilder(int capacity) |
StringBuilder(String str) |
eg.
代码语言:javascript复制class StringBufferTest{
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();//创建一个容量为16的StringBuffer对象
StringBuffer s2 = new StringBuffer("我是中国人");
System.out.println(s2);
StringBuffer s3 = new StringBuffer(100);//创建一个容量为100的StringBuffer对象
}
}
七、方法
方法名 | 作用 |
---|---|
StringBuilder append(char c) | 在字符串尾巴追加字符 |
int capacity() | 当前StringBuffer/StringBuilder的容量 |
char charAt(int index) | 返回指定位置的字符 |
StringBuilder delete(int start, int end) | 删除[start, end)范围的字符 |
StringBuilder deleteCharAt(int index) | 删除指定位置的字符 |
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) | 将字符串转换成char复制到dst数组中 |
int indexOf(String str) | 返回str第一次出现的位置 |
int lastIndexOf(String str) | 返回str最后一次出现的位置 |
StringBuilder insert(int offset, char c) | 在offset位置插入字符 |
int length() | 返回字符串长度 |
StringBuilder replace(int start, int end, String str) | 将[start, end)的内容替换成str |
StringBuilder reverse() | 字符串翻转 |
void setCharAt(int index, char ch) | 将index位置的字符设置为ch |
String substring(int start) | 从start开始截取字串 |
String substring(int start, int end) | 截取start到end – 1的字符串 |
void setLength(int newLength) | 设置StringBuffer/StringBuilder的长度,默认补空格,并自动扩充容量 |
CharSequence subSequence(int start, int end) | 和substring一样,只不过返回CharSequence |
eg.
代码语言:javascript复制class StringBufferTest{
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
s1.append("a");
s1.append("b").append('c').append('d').append('e').append('f').append("f");
System.out.println(s1);//ab
System.out.println(s1.capacity());//16
System.out.println(s1.charAt(2));//c
//System.out.println(s1.delete(1, 3));//adef
//System.out.println(s1.deleteCharAt(2));//abdef
System.out.println(s1.indexOf("c"));//2
System.out.println(s1.lastIndexOf("f"));//6
System.out.println(s1.insert(1, 123));//a123bcdeff
char[] c = new char[20];
s1.getChars(0, s1.length(), c, 0);
System.out.println(Arrays.toString(c));//[a, 1, 2, 3, b, c, d, e, f, f, , , , , , , , , , ]
System.out.println(s1.length());//10
System.out.println(s1.replace(1, 4, "A"));//aAbcdeff
//System.out.println(s1.reverse());//ffedcbAa
s1.setCharAt(1, 'a');
System.out.println(s1);//aabcdeff
System.out.println(s1.substring(2));//bcdeff
System.out.println(s1.substring(2,5));//bcd
System.out.println(s1.subSequence(1, 3));//ab
s1.setLength(100);
System.out.println(s1.length());//100 直接在后面追加空格
System.out.println(s1.capacity());//100
}
}
StringBuffer和StringBuilder构造方法和方法一样!
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160695.html原文链接:https://javaforall.cn