二、StringBuffer类&StringBuilder类 2.1 简介
java.lang.StringBuffer、StringBuilder代表可变的字符序列,可以对字符 串内容进行增删,此时不会产生新的对象。
很多方法与String相同
作为参数传递时,方法内部可以改变值。
2.2 String VS StringBuffer VS StringBuilder
String、StringBuffer、StringBuilder三者的异同?
String:不可变的字符序列;底层使用char[]存储
StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
源码分析
我们使用new String()创建字符串的时候:
String str = new String(); //底层是这样的:char[] value = new char[0]; String str1 = new String("abc"); //底层是这样的:char[] value = new char[]{\'a\',\'b\',\'c\'};
我们使用new StringBuffer()创建字符串的时候:
StringBuffer test = new StringBuffer();// 无参:底层是这样的:char[] value = new char[16];底层创建了一个长度是16的数组。 StringBuffer test2 = new StringBuffer("abd");// 有参:底层是这样的:char[] value = new char[test2.leng()+16]StringBuffer底层部分源码:
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence { /** * A cache of the last value returned by toString. Cleared * whenever the StringBuffer is modified. */ private transient char[] toStringCache; /** use serialVersionUID from JDK 1.0.2 for interoperability */ static final long serialVersionUID = 3388685877147921107L; /** * Constructs a string buffer with no characters in it and an * initial capacity of 16 characters. */ public StringBuffer() { super(16); } }从中我们可以看出StringBuffer的无参构造器,默认容量是16。点击super我们去StringBuffer的父类看看。
从中我们可以看出,new了长度为16的字符数组,并且给了value这个变量。
有参数:
几个问题
@Test public void test1() { StringBuffer str1 = new StringBuffer("abd"); System.out.println(str1.length()); }(1)System.out.println(str1.length());结果为多少?为什么不为str1.length()+16?
答:3。因为它统计的是你append进去的数量。
(2)扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
答:默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。
指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)
2.3 StringBuffer类的常用方法注意:
String的常用方法,StringBuffer和StringBuilder都有,同时它们两个有些String没有的方法
StringBuilder的常用方法和StringBuffer的一样,只不过是同步方法,线程安全。
StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
StringBuffer delete(int start,int end):删除指定位置的内容
StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse() :把当前字符序列逆转
public int indexOf(String str)
public String substring(int start,int end)
public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch)
当append和insert时,如果原来value数组长度不够,可扩容。
如上这些方法支持方法链操作。
总结: 增:append(xxx) 删:delete(int start,int end) 改:setCharAt(int n ,char ch) / replace(int start, int end, String str) 查:charAt(int n ) 插:insert(int offset, xxx) 长度:length(); *遍历:for() + charAt() / toString() @Test public void test1() { StringBuffer buffer = new StringBuffer("abc"); /*增*/ buffer.append(2); System.out.println(buffer); /*删*/ buffer.delete(1,3); System.out.println(buffer); /*改1*/ buffer.setCharAt(0,\'s\'); System.out.println(buffer); /*改2*/ buffer.replace(0,1,"cxk"); System.out.println(buffer); /*插*/ buffer.insert(1,"SSS"); System.out.println(buffer); /*长度*/ int length = buffer.length(); System.out.println(length); /*遍历*/ for (int i = 0; i < buffer.length(); i++) { System.out.print(buffer.charAt(i)+" "); } System.out.println("\n================="); /*转为字符串*/ System.out.println(buffer.toString()); } 2.4 三者效率对比 @Test public void test2() { //初始设置 long startTime = 0L; long endTime = 0L; String text = ""; StringBuffer buffer = new StringBuffer(""); StringBuilder builder = new StringBuilder(""); //开始对比 startTime = System.currentTimeMillis();// 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)); }