java中的String类与StringBuffer类
每日一言
Just what is right and what is wrong…? To begin with, just who is the enemy I must defeat? – Rentaro Satomi
from Black Bullet
String类创建
String类的构造方法有11种,我们这里了解两种最基本的创建方法:
1 |
|
在java中,双引号括起来的文本(如 "Hello World"
)被称为 字符串字面量 ,它们会被自动视为 String
类型的对象。
String类的不可变性
Java中的String类低层封装时是通过一个 final
的字符数组(char()
) 实现的,导致这个数组的内容在对象创建后不能被修改。任何对于String的修改操作都会创建一个新的String类。
验证不可变性:
1 |
|
运行结果:
1 |
|
创建格式化字符串
如果要输出格式化字符串,可以使用 System.out.printf()
函数:
1 |
|
如果想要创建可以复用的String类的格式化字符串,可以使用 .format()
方法:
1 |
|
String中的常用方法
获取字串
1
2
3
4String str1 = "abcdef";
String str2 = str1.substring( 0, 3); //获取下标[0,3)的字符组成的字串:abc
String str3 = str1.substring(3); //获取下标[3,)的字串: def连接字符串
1
2
3
4String str1 = "hello";
String str2 = " world";
String str3 = str1.concat(str2); //使用contact方法
String str4 = str1 + str2; //使用+相连主要差别:
特性 concat() +
运算符参数类型 只能拼接 String
类型,其他类型会报错。可以拼接任意类型,会自动转换为字符串。调用toString() null
的处理如果参数是 null
,会抛出NullPointerException
。如果参数是 null
,会将其视为字符串"null"
。性能 性能稍高,因为直接操作字符串对象。 性能稍低,可能涉及 StringBuilder
的隐式调用。代码可读性 可读性稍差,适合明确的字符串拼接操作。 可读性更高,代码更简洁。 比较字典序
1
2
3
4
5
6
7String str1 = "a";
String str2 = "b";
String str3 = "c";
String str4 = "b";
System.out.println(str2.compareTo(str1)); //当str2大于str1时,返回正数
System.out.println(str2.compareTo(str3)); //当str2小于str3时,返回负数
System.out.println(str2.compareTo(str4)); //当str2等于str4时,返回0通过下标获取字符
1
2
3
4
5String str1 = "abcd";
System.out.println(str1.charAt(0)); //a
System.out.println(str1.charAt(1)); //b
System.out.println(str1.charAt(2)); //c
System.out.println(str1.charAt(3)); //d前缀判断
1
2
3String str1 = "abcd";
str1.startsWith("ab") //判断字符串是否以ab开头
str1.startsWith("ab",1) //从下标1开始的字串是否以ab开头后缀判断
1
2String str1 = "abcd";
str1.endsWith("cd") //检查后缀是否为cd。只有这一个版本查找指定字串第一次出现的位置
1
2
3String str1 = "aabcd";
str1.indexOf("bc"); //返回bc第一次出现的下标:2
str1.indexOf("bc", 3); //从下标3开始的部分中bc第一次出现的下标:-1(没找到返回-1)查找指定字串最后一次出现的位置
1
2
3String str1 = "abcabcd";
str1.lastIndexOf("bc") //返回bc在字符串中最后一次出现的下标:4
str1.lastIndexOf("bc", 3) //从下标3开始反向搜索:1 (未找到返回-1)判断字符串是否相等
1
2
3
4String str1 = "aabcd";
String str2 = "abcd";
boolean isEqual = str1.equals(str2); //判断str1和str2的内容是否相等
str1 == str2; // 比较对象的引用是否相等
其他String类的方法可以参见:Java String 类 | 菜鸟教程
StringBuffer类
在上面的演示中,由于Sting类的不可修改性,在每次对于String对象进行修改时,都会产生一个新的String对象,这显然是不高效的。
StringBuffer类正是用于解决这一问题。如果你需要对于一个字符串进行多次修改,使用StingBuffer类会更快,它可以直接在对象本身上修改。
StringBuffer类的创建
StringBuffer 的创建必须使用StringBuffer的构造方法来创建。但是与String类创建时必须直接赋值不同。StringBuffer类有三种构造方式
1 |
|
StringBuffer类在容量不够时会自动扩充容量:假设现在的容量为x
- 比较2x+2与字符串长度的大小
- 如果2x+2更大,则创建一个容量为2x+2大小的char[]
- 否则创建一个和字符串长度相等的char[]
- 将旧数组的内容复制到新数组中
- 用新数组替换旧数组
我们看以下示范代码:
1 |
|
运行结果如下:
1 |
|
虽然StringBuffer会自动扩容,但是频繁扩容会影响性能。因此如果预先知道大致需要的容量,最好在创建时就指定合适的初始容量。
StringBuffer的编辑方法
我们知道创建StringBuffer就是因为我们需要大量的编辑这个字符串,接下来我们来看看有哪些方法可以编辑StringBuffer实例
在末尾添加字串
1
2StringBuffer str = new StringBuffer();
str.append("abcdefghijklmnopqrstuvwxyz"); // append方法会将指定的字符串添加到末尾将字符串反转
1
2
3StringBuffer str = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
str.reverse(); //reverse()会直接将字符串反转
System.out.println(str); // Output: zyxwvutsrqponmlkjihgfedcba删除一段
1
2
3StringBuffer str = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
str.delete(0, 1); //删除范围在[0,1)之间的字符串
System.out.println(str); // Output: bcdefghijklmnopqrstuvwxyz在字符串中插入
1
2
3StringBuffer str = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
str.insert(2, "123"); // 在下标为2的位置插入,后续的字符串全部后移
System.out.println(str); // Output: ab123cdefghijklmnopqrstuvwxyz替代
1
2
3StringBuffer str = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
str.replace(1, 3, "12345456789"); //将指定下标的内容替换为指定的字符串,长度可以不一
System.out.println(str); // Output: a12345456789defghijklmnopqrstuvwxyz
除了以上修改专门的方法以外,StringBuffer类还有很多与String都有的函数,可以参考:Java StringBuffer 和 StringBuilder 类 | 菜鸟教程
StringBulider类
StringBuilder类与StringBuffer类差别为:
- StringBulider 类性能更好,但是不是线程安全的
- StringBuffer 类是线程安全的,可以多线程同步访问
因此在单线程时,可以通过使用StringBuilder类来提高性能