目录
1.字符串处理的工具类
对于在 Java 编程中有着重要作用的引用数据类型——字符串,Java 提供了用于处理字符串的三个类,分别是 String 、StringBuilder 与 StringBuffer 。
其中 String 类负责对字符串的创建与操作,但由于 String 类的值其实是一个被 final 修饰的 char 数组,因此它在堆中值是不可变的,每次想要改变 String 变量的值都会生成新的 String 对象,并把它的地址赋值给 String 变量。当数据量过大的时候,不仅效率极低,而且极大程度的浪费了有限的内存空间。
与 String 类不同的是,StringBuffer 和 StringBuilder 类的值虽然也是 char 数组,但并没有被 final 修饰。因此能够被多次的修改,并且不产生新的未使用对象;并且 StringBuffer 在实例化时就创建了一个长度为16的数组,当达到最大长度时才成倍扩充。所以当要对字符串进行扩充的操作时,需要使用 StringBuffer 和 StringBuilder 类提高程序的运行效率。
其中StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的,即不能实现线程的同步。由于 StringBuilder 不关心同步问题,因此相较于 StringBuffer 有速度优势,所以多数情况下建议使用StringBuilder类。若在开发过程中要求线程的同步(如游戏开发),那么必须使用 StringBuffer 以确保线程安全。
2.三者的继承关系
3.String 类的使用
(1)String 类常用的构造方法
①String 类的默认构造方法
public String() {
this.value = "".value;
}
在此需要注意的是,对于默认构造,它的值并不是null,而是一个空字符串""。
②String类的数组参数构造方法
//直接赋值
String str1 = "adc";
//通过构造方法赋值
char[] value = {'a','b','c'};
String str2 = new String(value);
需要注意的是,用这两种方式为 String 对象赋值效果是一样的。
③参数是 StringBuilder 与 StringBuffer 的构造方法
这两个构造方法是将参数类型转换为String类型,方便字符串的其他操作。
public String(StringBuffer buffer);//分配一个新的字符串,它包含字符串缓冲区参数中当前包含的字符序列
public String(StringBuilder builder);//分配一个新的字符串,它包含字符串生成器参数中当前包含的字符序列
(2)String 类常用的成员方法
//判断方法
public boolean equals(Object anObject);//将此字符串与指定的对象比较
public boolean equalsIgnoreCase(String anotherString);//将此String与另一个String比较,不考虑大小写
public int compareTo(String str);//按字典顺序比较两个字符串
public int compareToIgnoreCase(String str);//按字典顺序比较两个字符串,不考虑大小写
boolean contains(CharSequence s);//判断字符串中是否包含指定字符
//获取方法
public int length();//返回此字符串的长度
public String concat(String str);//指定字符串连接到此字符串的结尾
public char charAt(int index);//返回指定索引处的char值
public int indexOf(String str);//返回指定子字符串第一次出现在该字符串内的索引
public String substring(int beginIndex);//截取索引从beginIndex开始到字符串结尾的子字符串
public String substring(int beginIndex, int endIndex);//截取索引从beginIndex开始到endIndex-1结尾的子字符串
public String trim();//返回字符串的副本,忽略前导空白和尾部空白。
//转换方法
public char[] toCharArray();//将此字符串转换为新的字符数组
public byte[] getBytes();//使用平台的默认字符集(如ASCII编码)将该 String编码转换为新的字节数组
public String replace(CharSequence target, CharSequence replacement);//将与target匹配的字符序列使用replacement字符序列替换
public String[] split(String regex);//根据给定正则表达式的匹配拆分此字符串
下面举例说明
public static void main(String[] args) {
String str = "123abc123";
System.out.println("原数组:"+str);
System.out.println("str与123abc123相等?"+str.equals("123abc123"));
System.out.println("比较str与123cde456的大小:"+str.compareTo("123cde456"));
System.out.println("str中是否含有abc?"+str.contains("abc"));
System.out.println("str的长度:"+str.length());
System.out.println("abc的索引值:"+str.indexOf("abc"));
System.out.println("str中索引值为3的字符:"+str.charAt(3));
System.out.println("截取索引值从2到4的字符串:"+str.substring(2,5));
System.out.println("把字符串变为字符数组:"+Arrays.toString(str.toCharArray()));
System.out.println("字符串变为默认编码格式的数组:"+Arrays.toString(str.getBytes()));
System.out.println("以adc分割字符串为字符串数组:"+Arrays.toString(str.split("abc")));
System.out.println("把adc替换为def后的字符串:"+str.replace("abc","def"));
}
结果为:
原数组:123abc123
str与123abc123相等?true
比较str与123cde456的大小:-2
str中是否含有adc?true
str的长度:9
abc的索引值:3
str中索引值为3的字符:a
截取索引值从2到4的字符串:3ab
把字符串变为字符数组:[1, 2, 3, a, b, c, 1, 2, 3]
字符串变为默认编码格式的数组:[49, 50, 51, 97, 98, 99, 49, 50, 51]
以adc分割字符串为字符串数组:[123, 123]
把adc替换为def后的字符串:123def123
需要注意的是,对于返回值类型为 String 的成员方法,在底层代码的实现中最终返回的均为一个新的 String 对象,而不是直接修改原来的 String 对象。
4.StringBuilder 类的使用
(1)StringBuilder 类常用的构造方法
public StringBuilder();//构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符
public StringBuilder(int capacity);//构造一个不带任何字符的字符串生成器,其初始容量由 capacity 参数指定
public StringBuilder(String str);//构造一个字符串生成器,并初始化为指定的字符串内容
需要注意的是:第三个构造方法参数不能为 null 。因为在底层代码实现中,需要获取参数的长度,而 null 是无法获取长度的,因此运行时会出现空指针异常。
StringBuilder stringBuilder = new StringBuilder(null);//空指针异常
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
(2)StringBuilder 类常用的成员方法:append() 方法
该方法的作用是在原字符串之后追加任意类型的参数,是直接对原字符串进行的操作,并没有创建新的引用对象。
public static void main(String[] args) {//抛出异常
String str1 = "adc";
String str2 = new String("3r5");
//把str1转换为StringBuilder
StringBuilder stringBuilder1 = new StringBuilder(str1);
//依次追加不同的类型
StringBuilder stringBuilder2 = stringBuilder1.append(str2).append(1).append(23.5);
System.out.println(stringBuilder1);//打印原先的字符串(地址不变,值已被改变)
System.out.println(stringBuilder2);//改变后的字符串
//判断地址值是否被改变(是否引用了新的对象)
System.out.println(stringBuilder1 == stringBuilder2);
}
结果为:
adc3r5123.5
adc3r5123.5
true//说明地址相等,没有被改变
由此可见,我们在使用 append() 方法时无需接受返回值,直接使用被操作的字符串即可。
(3)字符串拼接的实现原理
字符串的拼接其实就是调用了 StringBuilder 中的构造方法与 append() 方法,它们的实现原理是相同的。
public static void main(String[] args) {//抛出异常
String str1 = "adc";
//字符串拼接
String str2 = str1 + 1 + 23.5 + true;
System.out.println(str2);
//使用StringBuilder
String str3 = new StringBuilder(str1).append(1).append(23.5).append(true).toString();
System.out.println(str3);
}
结果为:
adc123.5true
adc123.5true
对于 StringBuffer ,它和 StringBuilder 继承了同一个抽象父类 AbstractStringBuilder ,使用方式基本相同,因此不做详细介绍。唯一不同的是,StringBuffer 中的方法使用了线程同步机制来保证线程的安全性。
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}