一、StringBuffer类
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
/*
StringBuffer类是对String类的一个增强
1)原先的字符串是final类型的,但是java.lang.StringBuffer代表
的是可变的字符序列,可以对字符串内容进行增删。很多方法与String相同
而StringBuffer是可变长度的。
2)StringBuffer是一个容器
创建一个StringBuffer对象,然后进去看看类图
StringBuffer实现了Serializable接口
父类AbstractStringBuilder实现了Appendable和CharSequence接口
继承Object
3)因为实现了Serializable,所以StringBuffer的对象是可以串行化的
*/
public class StringBufferClass01 {
public static void main(String[] args) {
StringBuffer hello = new StringBuffer("hello");
// 如果StringBuffer这里有内容hello,这个内容是放到什么地方的呢?
// 在StringBuffer的父类中有char[] value;这样的一个数组
// 这个value是用于存放字符的,所以
// 4)char数组value不是一个final类型,该value是存放我们的字符串内容
// 因此是存放在堆当中的不是常量池,StringBuffer是一个final类不能被继承
/*
String与StringBuffer的对比
1、String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上
就是更改地址,效率较低//private final char value[];
2、StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新
实际上可以更新内容,不用每次更新地址,效率较高//char[] value;这个放到堆当中
举例说明:
String的对象是在堆当中,但是其字符串常量是在常量池当中,需要创建新的对象
StringBuffer对象是在堆当中的,字符串常量也是在堆当中的,首先开辟一大块空间,
如果空间不够了才会扩容,如果空间足够可以随意添加修改。
5)因为StringBuffer字符内容是存在char[] value,所以在变化的时候不用每次都更换地址(即不是每次都创建新的对象)
所以效率高于String
*/
}
}
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
/*
StringBuffer的构造器
1、StringBuffer()
2、StringBuffer(CharSequence seq)
3、StringBuffer(int capacity)
4、StringBuffer(String str)
*/
public class StringBufferClass02 {
public static void main(String[] args) {
// 1、创建一个大小为16的char[], 用于存放字符内容
StringBuffer stringBuffer = new StringBuffer(); // super(16);
// 2、StringBuffer(CharSequence seq),这个是直接放到char数组当中去了,这个使用不多
// 3、还可以通过构造器来指定char[]大小
StringBuffer stringBuffer1 = new StringBuffer(100);
// 4、第四种是可以传入一个String字符串,通过字符串创建一个StringBuffer,大小是字符串的长度加上16
StringBuffer hello = new StringBuffer("hello");
// 5、String和StringBuffer之间的转换
// 1)将String转换成StringBuffer-第一种
String str = "hello tom";
StringBuffer stringBuffer2 = new StringBuffer(str);
// 将String转换成StringBuffer-第二种
StringBuffer stringBuffer3 = new StringBuffer();
stringBuffer3 = stringBuffer3.append(str);
// 2)StringBuffer转换成为String-第一种
StringBuffer hello1 = new StringBuffer("hello");
String s = hello1.toString();
// StringBuffer转换成String-第二种
String s1 = new String(hello1);
}
}
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
/*
StringBuffer的常见方法
1、append
2、delete
3、replace
4、indexOf
5、insert
6、length
*/
public class StringBufferClass03 {
public static void main(String[] args) {
// 1、append添加
StringBuffer sb = new StringBuffer("hello");
sb.append(','); // hello,
sb.append("张三丰"); // hello,张三丰
sb.append("赵敏").append(100).append(true).append(10.5); // hello,张三丰赵敏100true10.5
System.out.println(sb); // 因为修改的是容器,没有创建新的对象,可以直接对容器进行修改,打印调用的是toString方法
// 2、delete删除
sb.delete(11, 14); // 删除是根据索引来进行删除>=start && <end的字符
System.out.println(sb); // 对应这里就是删除100
// 3、替换replace
sb.replace(9, 11, "周芷若"); // [9,11)替换成周芷若
System.out.println(sb); // 这里相当于将赵敏替换成周芷若
// 4、indexOf,查找指定的子串第一次出现的索引位置,如果找不到就返回-1
int indexOf = sb.indexOf("张三丰");
System.out.println(indexOf);
// 5、insert,在索引为9的位置插入一个字符串,原来索引为9的内容后移
sb.insert(9, "赵敏");
System.out.println(sb);
// 6、length
System.out.println(sb.length()); // 统计有多少个字符
}
}
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
public class StringBufferClass04 {
// public static void main(String[] args) {
// /*
// 关于StringBuffer类的课堂测试题:
// 第一题:看看下面的代码输出什么?为什么?
// */
// String str = null;
// StringBuffer sb = new StringBuffer();
// sb.append(str); // 这里到底是否存在问题需要查看源码
// /*
// value[c++] = 'n';
// value[c++] = 'u';
// value[c++] = 'l';
// value[c++] = 'l';
// 将空转换成了null字符串
// */
// System.out.println(sb.length()); // 4,因为是null字符串,所以这里显示的是4
// System.out.println(sb); // null
// StringBuffer sb1 = new StringBuffer(str); // 看构造器的源码super(str.length() + 16); null.产生空指针异常
// System.out.println(sb1);
// }
public static void main(String[] args) {
/*
第二题
输入商品名称和商品价格,要求打印效果示例,使用前面学习的方法完成
商品名称 商品价格
手机 123,564,59
价格的小数点前面每三位使用逗号隔开
思路分析:
1、定义一个Scanner对象,接收用户输入的价格String
2、希望使用到StringBuffer的insert方法,需要将String转换成StringBuffer
3、然后使用相关方法进行字符串的处理
*/
String price = "8123564.59";
StringBuffer sb = new StringBuffer(price);
for (int i = sb.lastIndexOf(".")-3; i > 0; i -= 3) {
sb = sb.insert(i, ",");
}
System.out.println(sb);
}
}
二、StringBuilder
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
public class StringBuilderClass05 {
public static void main(String[] args) {
// 1、StringBuilder继承了AbstractStringBuilder类
// 2、实现了Serializable,说明StringBuilder对象是可以串行化的(对象可以在网络中传输,可以放到文件中)
// 3、StringBuilder是final类,不能被继承
// 4、StringBuilder对象字符序列仍然是存放到父类当中AbstractStringBuilder的char[] value;
// 因此,字符序列是堆中
// 5、StringBuilder的方法,没有做互斥的处理,即没有synchronized关键字,因此在单线程的情况下使用StringBuilder
StringBuilder stringBuilder = new StringBuilder();
}
}
/*
StringBuilder类的基本介绍
1、一个可变的字符序列,此类提供了一个与StringBuffer兼容的api,但是不能保证
同步(StringBuilder不是线程安全的)。
该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的使用。
如果可能,建议优先采用该类,因为大多数实现中,它比StringBuffer要快。
2、在StringBuilder上主要的操作是append和insert方法,可以重载这些方法,
以接收任意类型的数据。
我们也来看看类图,StringBuilder同样实现了和StringBuffer一样的接口,继承了Object类
*/
package com.day5_21;
/**
* @author alice_huijing
* @version 1.0
*/
public class StringBuilderClass06 {
public static void main(String[] args) {
// 测试一下String、StringBuffer、StringBuilder之间的一个效率
String text = "";
long startTime = 0L;
long endTime = 0L;
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
/*
String,StringBuffer和StringBuilder的比较
1、StringBuilder和StringBuffer非常类似,均代表可变的字符序列,而方法也一样
2、String是不可变字符序列,效率低,但是复用率高
3、StringBuffer是可变字符序列、效率较高(增删)、线程安全
StringBuffer源码中很多的方法前面都加上了一个关键字叫做synchronized
这个是同步的意思,一个线程在操作的时候另外一个线程就不能操作了。
4、StringBuilder:可变字符序列,效率最高,线程不安全
5、String使用注意说明:
String s = "a"; 创建了一个字符串
s += "b"; // 实际上原来的a字符串对象已经被丢弃,现在又产生了一个字符串s + "b",也就是ab
如果多次指向这些改变串内容的操作,就会导致大量副本字符串对象存留在内存当中,降低效率,如果这样
的操作放到循环当中,就会极大影响程序的性能。
结论就是:如果我们对String做大量修改,就不要使用String
StringBuffer的执行时间:3
StringBuilder的执行时间:2
String的执行时间:1468
虽然是这样,但是不同的类在不同的地方具有不同的使用场景:
使用的结论:
1、如果字符串存在大量的修改操作,一般使用StringBuffer 或者 StringBuilder
2、如果字符串中存在大量的修改操作,并且单线程的情况,使用StringBuilder
3、如果字符串中存在大量的修改操作,并且多线程的情况,使用StringBuffer
4、如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等
*/