1 StringBuffer类
基本介绍:StringBuffer 是 Java 标准库中的一个类,用于处理可变的字符串序列。它与不可变的字符串 String 类似,但是 StringBuffer 允许对字符串内容进行修改和操作,适用于需要频繁拼接和修改字符串的情况,尤其在多线程环境下推荐使用线程安全版本的 StringBuilder。
- 可变性: StringBuffer 对象的内容可以被修改,包括添加、插入、删除和替换字符等操作。
- 线程安全性: StringBuffer 是线程安全的,即多个线程同时对一个 StringBuffer 进行操作时,不会出现数据不一致的问题。这是通过使用同步机制来实现的,但这也会带来一些性能开销。如果不需要线程安全,推荐使用性能更好的 StringBuilder。
- 构造方法: StringBuffer 提供了多个构造方法,可以通过字符串、字符数组、初始容量等来初始化。 StringBuffer() : 构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。(容量是可以自动扩容的) StringBuffer(int capacity) :构造一个不带字符,但具有指定初始容量的字符串缓冲区。 StringBuffer(String str) :构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。该字符串的初始容量为 16 加上字符串参数的长度。
- 常用方法: StringBuffer 提供了一系列的方法用于字符串操作,包括:
append(String str):将指定的字符串追加到当前StringBuffer对象的末尾。 insert(int offset, String str):在指定的位置插入字符串。 delete(int start, int end):删除指定位置范围内的字符。 replace(int start, int end, String str):用指定的字符串替换指定位置范围内的字符。 reverse():反转StringBuffer对象中的字符顺序。 toString():将StringBuffer对象转换为String对象。
- 性能: 由于 StringBuffer 使用了同步机制以实现线程安全,因此在单线程环境中,性能可能比 StringBuilder 差一些。如果不需要线程安全,并且在单线程环境下频繁修改字符串内容,推荐使用 StringBuilder。
2 StringBuilder类
StringBuilder类可以理解为一个字符串缓冲区,它提供一个可变的字符序列,可以在该序列上进行修改操作,比如追加,插入,删除和替换等。与String类不同的是,String类的修改操作每次都会创建一个新的字符串对象,而StringBuilder类的修改操作都是在原有的字符序列上进行的,不会创建新的对象,因此在频繁进行字符串操作时,StringBuilder类的效率比String类高。
StringBuilder类是一个可变的字符串,允许进行多次修改而不创建新的String对象。它是AbstractStringBuilder类的子类,实现了CharSequence接口和java.io.Serializable接口。
该类定义了四个构造函数,分别为不带参数的构造函数、指定初始容量的构造函数、包含CharSequence的构造函数和包含String的构造函数。其中,不带参数的构造函数会创建一个长度为16的StringBuilder对象。指定初始容量的构造函数会根据参数capacity创建一个StringBuilder对象。包含CharSequence的构造函数和包含String的构造函数会创建一个容量为参数长度加16的StringBuilder对象,并将参数序列追加到StringBuilder对象末尾。
3 StringBuffer常见方法
![[Pasted image 20240713155257.png]]
测试代码
public static void main(String[] args) {
StringBuffer s1=new StringBuffer("abcd1234!?,;");
StringBuffer s2=new StringBuffer("987654321987654");
StringBuffer s3=new StringBuffer("987654321");
System.out.println("↓↓↓StringBuffer类的一些常用方法如下↓↓↓");
System.out.println("-----------------------------------------------------");
System.out.println("字符串s1的长度为:" + s1.length());//返回字符串的实际长度
System.out.println("-----------------------------------------------------");
System.out.println("字符串s1所占容器的大小为:" + s1.capacity());//返回字符串所占容器的总大小
System.out.println("-----------------------------------------------------");
System.out.println("获取字符串s1中第2个位置的字符:" + s1.charAt(2));
System.out.println("-----------------------------------------------------");
System.out.println("子字符串'654'第一次出现在字符串s2中的索引为:" + s2.indexOf("654"));
System.out.println("从指定的索引6开始搜索,返回子字符串'654'第一次出现在字符串s2中的索引:" + s2.indexOf("654",6));
System.out.println("-----------------------------------------------------");
System.out.println("子字符串'987'最后一次出现在字符串s2中的索引为:" + s2.lastIndexOf("987"));
System.out.println("从指定的索引5开始反向搜索,返回字符串'87'在字符串s2中最后一次出现的索引:" + s2.lastIndexOf("87",5));
System.out.println("-----------------------------------------------------");
s1.append('x');//在字符串s1的末尾添加字符'c'
s1.append("Java");//在字符串s1的末尾添加字符串"Java"
System.out.println("修改后的字符串s1为:" + s1);
System.out.println("-----------------------------------------------------");
s1.insert(4,"abcd");//在第4个位置插入字符串"abcd"
System.out.println("修改后的字符串s1为:" + s1);
System.out.println("-----------------------------------------------------");
s1.deleteCharAt(1);//删除字符串s1中第一个位置的字符
s1.delete(2,5);//删除字符串s1中第2到第4个位置的字符
System.out.println("修改后的字符串s1为:" + s1);
System.out.println("-----------------------------------------------------");
s1.replace(4,8,"5678");//将字符串s1中第4到第7个位置的字符串修改为"5678"
System.out.println("修改后的字符串s1为:" + s1);
System.out.println("-----------------------------------------------------");
s1.setCharAt(1,'b');//将字符串s1中第一个位置的字符修改为'b'
System.out.println("修改后的字符串s1为:" + s1);
System.out.println("-----------------------------------------------------");
s2.reverse();//将字符串s2反转
System.out.println("修改后的字符串s2为:" + s2);
System.out.println("-----------------------------------------------------");
System.out.println("截取字符串s1从第4个位置开始到结尾:" + s1.substring(4));
System.out.println("-----------------------------------------------------");
System.out.println("截取字符串s1从第4个位置开始到第7个位置结尾:" + s1.substring(4,8));
System.out.println("-----------------------------------------------------");
System.out.println("获取s1的变量类型:" + s1.getClass().getName());
System.out.println("将对象信息转化为字符串:" + s2.toString());
}
输出结果:
↓↓↓StringBuffer类的一些常用方法如下↓↓↓
-----------------------------------------------------
字符串s1的长度为:12
-----------------------------------------------------
字符串s1所占容器的大小为:28
-----------------------------------------------------
获取字符串s1中第2个位置的字符:c
-----------------------------------------------------
子字符串'654'第一次出现在字符串s2中的索引为:3
从指定的索引6开始搜索,返回子字符串'654'第一次出现在字符串s2中的索引:12
-----------------------------------------------------
子字符串'987'最后一次出现在字符串s2中的索引为:9
从指定的索引5开始反向搜索,返回字符串'87'在字符串s2中最后一次出现的索引:1
-----------------------------------------------------
修改后的字符串s1为:abcd1234!?,;xJava
-----------------------------------------------------
修改后的字符串s1为:abcdabcd1234!?,;xJava
-----------------------------------------------------
修改后的字符串s1为:accd1234!?,;xJava
-----------------------------------------------------
修改后的字符串s1为:accd5678!?,;xJava
-----------------------------------------------------
修改后的字符串s1为:abcd5678!?,;xJava
-----------------------------------------------------
修改后的字符串s2为:456789123456789
-----------------------------------------------------
截取字符串s1从第4个位置开始到结尾:5678!?,;xJava
-----------------------------------------------------
截取字符串s1从第4个位置开始到第7个位置结尾:5678
-----------------------------------------------------
获取s1的变量类型:java.lang.StringBuffer
将对象信息转化为字符串:456789123456789
4 String、StringBuffer、StringBulider区别
(1)String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上是更改地址,效率比较低
- private final char value[];,放在常量池中
(2)StringBuffer保存的是字符串变量,里面的值可以更改,每次更新实际上可以更细内容,不用每次更新地址,效率比较高
- char[] value;,放在堆中
(3)String与StringBuffer相互转换
public class StringAndStringBuffer {
public static void main(String[] args) {
//看 String-->StringBuffer
String str = "hello";
//方式1
// 这里只是把str传入到StringBuffer的构造器中,对原来的str没有影响
StringBuffer stringBuffer = new StringBuffer(str);
//方式2
//使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
//看看 StringBuffer -> String
StringBuffer stringBuffer3 = new StringBuffer("ywl");
//方式1:使用StringBuffer提供的toString方法
String s = stringBuffer3.toString();
//方式2:使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}
(4)StringBuffer和StringBuilder非常相似,他们都代表可变的字符序列,并且方法也一样
(5)String:不可变字符序列,效率低,但是它的复用率高
(6)StringBuffer:可变字符序列,效率高,效率较高(增删改查),线程安全
(7)StringBuilder:可变字符序列,效率最高,线程不安全
(8)String使用注意说明:
- stirng s = "a";//创建了一个字符串
- s +="b";//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+"b"也就是ab
- 如果多次执行,就会有大量的副本留在常量池中,降低效率,影响程序的性能
故:如果要对String做大量的修改,就不使用String类
5 总结
- 如果字符串存在大量的修改操作,一般使用 StringBuffer 或StringBuilder
- 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer
- 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等