StringBuffer简介
- StringBuffer直接继承自AbstractStringBuilder,实现了java.io.Serializable, CharSequence接口,故可序列化,可读的char型序列;
- 类似于String类,但StringBuffer是线程安全的可变字符串类;
- StringBuffer具有扩容机制,当需要存储字符的容量不大于当前得value数组长度,不会扩容,否则自动扩成当前容量的2倍+2;
- 从jdk5开始,新增的StringBuilder基本可StringBuffer一致,但是StringBuilder是非线程安全的,单线程中StringBuilder性能更好;
StringBuffer UML
StringBuffer API
字段
private transient char[] toStringCache; //最终保存字符串的数组
static final long serialVersionUID = 3388685877147921107L;
private static final java.io.ObjectStreamField[] serialPersistentFields
------------从AbstractStringBuilder继承的字段----------------
char[] value; //存储字符串
int count; //记录value数组中存储字符的个数
StringBuffer是可变的字符串类,主要是由于每次对字符串的修改前都会将toStringCache置为null,然后对value存储字符串的数组修改,最后将value中修改后的数组直接复制到toStringCache中,这样我们就保证了StringBuffer是一个可变的字符串数组,每次对同一字符的修改,都在toStringCache指向的同一块内存上。
所有API
- 构造函数
public StringBuffer()
public StringBuffer(int capacity)
public StringBuffer(String str)
public StringBuffer(CharSequence seq)
*直接继承或defalut方法
public default IntStream chars()
public default IntStream codePoints()
- Override或新增的方法
public synchronized int length() //得到value的实际存放的字符
public synchronized int capacity() //得到value的长度(容量长度大于等于长度)
public synchronized void ensureCapacity(int minimumCapacity) //函数内部实现扩容机制
public synchronized void trimToSize() //收缩length变成count
public synchronized void setLength(int newLength) //设置value数组长度,当newLength<count,字符串会别截断,newLength>count,多余内存会用' '填充;
public synchronized char charAt(int index) //返回下标字符
public synchronized void setCharAt(int index, char ch) //更新index位置的字符为新ch
public synchronized int codePointAt(int index)
public synchronized int codePointBefore(int index)
public synchronized int codePointCount(int beginIndex, int endIndex)
public synchronized int offsetByCodePoints(int index, int codePointOffset)
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,int dstBegin)
-------------------append相关方法------------------------------
public synchronized StringBuffer append(Object obj)
public synchronized StringBuffer append(String str)
public synchronized StringBuffer append(char[] str)
synchronized StringBuffer append(AbstractStringBuilder asb)
public synchronized StringBuffer append(CharSequence s)
public synchronized StringBuffer append(CharSequence s, int start, int end)
public synchronized StringBuffer append(char[] str, int offset, int len)
public synchronized StringBuffer append(boolean b)
public synchronized StringBuffer append(char c)
public synchronized StringBuffer append(int i)
public synchronized StringBuffer appendCodePoint(int codePoint)
public synchronized StringBuffer append(long lng)
public synchronized StringBuffer append(float f)
public synchronized StringBuffer append(double d)
public synchronized StringBuffer append(StringBuffer sb)
--------------------------delete相关方法-----------------------
public synchronized StringBuffer delete(int start, int end)
public synchronized StringBuffer deleteCharAt(int index)
--------------------------------------------------------------
public synchronized StringBuffer replace(int start, int end, String str)
--------------------得到子字符串--------------------------------
public synchronized String substring(int start)
public synchronized CharSequence subSequence(int start, int end)
public synchronized String substring(int start, int end)
--------------------insert相关方法
public synchronized StringBuffer insert(int index, char[] str, int offset,int len)
public synchronized StringBuffer insert(int offset, Object obj)
public synchronized StringBuffer insert(int offset, String str)
public synchronized StringBuffer insert(int offset, char[] str)
public StringBuffer insert(int dstOffset, CharSequence s)
public synchronized StringBuffer insert(int dstOffset, CharSequence s, int start, int end)
public StringBuffer insert(int offset, boolean b)
public synchronized StringBuffer insert(int offset, char c)
public StringBuffer insert(int offset, int i)
public StringBuffer insert(int offset, long l)
public StringBuffer insert(int offset, float f)
public StringBuffer insert(int offset, double d)
---------------------子串匹配方法----------------------------------------
public int indexOf(String str)
public synchronized int indexOf(String str, int fromIndex)
public int lastIndexOf(String str)
public synchronized int lastIndexOf(String str, int fromIndex)
---------------------------------------------------------------------------
public synchronized StringBuffer reverse() //逆序
public synchronized String toString()
------------------序列化-------------------------------------------------
private synchronized void writeObject(java.io.ObjectOutputStream s)
private void readObject(java.io.ObjectInputStream s)
StringBuffer 源码
package java.lang;
import java.util.Arrays;
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
//存储字符传的的数组,若修改字符串时该数据就会被清空,只保存数组最后一次修改的值
private transient char[] toStringCache;
static final long serialVersionUID = 3388685877147921107L;
//初始化继承的数组value大小16
public StringBuffer() {
super(16);
}
//自定义value数组大小
public StringBuffer(int capacity) {
super(capacity);
}
//构造一个StringBuffer初始化容量为具体的字符产长度+16
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
//构造一个StringBuffer初始化容量为具体的字符产长度+16
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
//返回实际存放的字符数
@Override
public synchronized int length() {
return count;
}
// 返回value数组的长度
@Override
public synchronized int capacity() {
return value.length;
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
//value收缩为实际含的字符数
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
// 重新设置数组长度
@Override
public synchronized void setLength(int newLength) {
toStringCache = null;
super.setLength(newLength);
}
// 返回value数组下标值
@Override
public synchronized char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
//返回指定索引字符的Unicode码
@Override
public synchronized int codePointAt(int index) {
return super.codePointAt(index);
}
// 返回指定索引的前一位索引位置的字符的unicode码 = codePointAt(int index-1)
@Override
public synchronized int codePointBefore(int index) {
return super.codePointBefore(index);
}
// 计算法从[beginIndex,endIndex)之间共多少unicode码
@Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
return super.codePointCount(beginIndex, endIndex);
}
//
@Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
return super.offsetByCodePoints(index, codePointOffset);
}
@Override
public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
int dstBegin)
{
super.getChars(srcBegin, srcEnd, dst, dstBegin);
}
// 先将toStringCache数组清空,在更新value[index]位置的字符
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
}
// 先将toStringCache数组清空,在value上追加新的字符串,
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
// 先将toStringCache数组清空,在value上追加新的字符串
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
//将指定的stringbuffer加入
public synchronized StringBuffer append(StringBuffer sb) {
toStringCache = null;
super.append(sb);
return this;
}
@Override
synchronized StringBuffer append(AbstractStringBuilder asb) {
toStringCache = null;
super.append(asb);
return this;
}
@Override
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
}
@Override
public synchronized StringBuffer append(char[] str) {
toStringCache = null;
super.append(str);
return this;
}
@Override
public synchronized StringBuffer append(char[] str, int offset, int len) {
toStringCache = null;
super.append(str, offset, len);
return this;
}
@Override
public synchronized StringBuffer append(boolean b) {
toStringCache = null;
super.append(b);
return this;
}
@Override
public synchronized StringBuffer append(char c) {
toStringCache = null;
super.append(c);
return this;
}
@Override
public synchronized StringBuffer append(int i) {
toStringCache = null;
super.append(i);
return this;
}
/**
* @since 1.5
*/
@Override
public synchronized StringBuffer appendCodePoint(int codePoint) {
toStringCache = null;
super.appendCodePoint(codePoint);
return this;
}
@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}
@Override
public synchronized StringBuffer append(float f) {
toStringCache = null;
super.append(f);
return this;
}
@Override
public synchronized StringBuffer append(double d) {
toStringCache = null;
super.append(d);
return this;
}
@Override
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
super.delete(start, end);
return this;
}
@Override
public synchronized StringBuffer deleteCharAt(int index) {
toStringCache = null;
super.deleteCharAt(index);
return this;
}
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
toStringCache = null;
super.replace(start, end, str);
return this;
}
@Override
public synchronized String substring(int start) {
return substring(start, count);
}
@Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
@Override
public synchronized StringBuffer insert(int offset, String str) {
toStringCache = null;
super.insert(offset, str);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, char[] str) {
toStringCache = null;
super.insert(offset, str);
return this;
}
@Override
public StringBuffer insert(int dstOffset, CharSequence s) {
// Note, synchronization achieved via invocations of other StringBuffer methods
// after narrowing of s to specific type
// Ditto for toStringCache clearing
super.insert(dstOffset, s);
return this;
}
@Override
public synchronized StringBuffer insert(int dstOffset, CharSequence s,
int start, int end)
{
toStringCache = null;
super.insert(dstOffset, s, start, end);
return this;
}
@Override
public StringBuffer insert(int offset, boolean b) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of b to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, b);
return this;
}
@Override
public synchronized StringBuffer insert(int offset, char c) {
toStringCache = null;
super.insert(offset, c);
return this;
}
@Override
public StringBuffer insert(int offset, int i) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of i to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, i);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuffer insert(int offset, long l) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of l to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, l);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuffer insert(int offset, float f) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of f to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, f);
return this;
}
/**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public StringBuffer insert(int offset, double d) {
// Note, synchronization achieved via invocation of StringBuffer insert(int, String)
// after conversion of d to String by super class method
// Ditto for toStringCache clearing
super.insert(offset, d);
return this;
}
/**
* @since 1.4
*/
@Override
public int indexOf(String str) {
// Note, synchronization achieved via invocations of other StringBuffer methods
return super.indexOf(str);
}
/**
* @since 1.4
*/
@Override
public synchronized int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
/**
* @since 1.4
*/
@Override
public int lastIndexOf(String str) {
// Note, synchronization achieved via invocations of other StringBuffer methods
return lastIndexOf(str, count);
}
/**
* @since 1.4
*/
@Override
public synchronized int lastIndexOf(String str, int fromIndex) {
return super.lastIndexOf(str, fromIndex);
}
/**
* @since JDK1.0.2
*/
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}
// toStirng 方法将value中保存的字符拷贝到toStringCache,保障了对同一个示例的操作,都在同一块内存,即保证了StringBuffer为可变字符串类
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
private static final java.io.ObjectStreamField[] serialPersistentFields =
{
new java.io.ObjectStreamField("value", char[].class),
new java.io.ObjectStreamField("count", Integer.TYPE),
new java.io.ObjectStreamField("shared", Boolean.TYPE),
};
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("value", value);
fields.put("count", count);
fields.put("shared", false);
s.writeFields();
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields();
value = (char[])fields.get("value", null);
count = fields.get("count", 0);
}
}
StringBuffer示例
package commonclass;
import java.util.stream.Collectors;
public class StringBufferTest {
public static void main(String[] args) {
/**
* StringBuffer构造函数
*/
StringBuffer stringBuffer1 = new StringBuffer();
StringBuffer stringBuffer2 = new StringBuffer(32);
StringBuffer stringBuffer3 = new StringBuffer("helloworld");
StringBuffer stringBuffer4 = new StringBuffer(new CharSequence() {
private char[] myString = "AHPU&SEU".toCharArray();
@Override
public int length() {
return myString.length;
}
@Override
public char charAt(int index) {
if (index < 0 || index > myString.length)
throw new IndexOutOfBoundsException();
return myString[index];
}
@Override
public CharSequence subSequence(int start, int end) {
return new java.lang.String(myString, start, end - start);
}
});
/**
* append
*/
stringBuffer1 = stringBuffer1.append("hi java");
System.out.println(stringBuffer1.length()); //7
System.out.println(stringBuffer1.capacity()); //16
stringBuffer1.append(1);
stringBuffer1.append('2');
stringBuffer1.append(3.14F);
stringBuffer1.append(2.78D);
stringBuffer1.append(true);
stringBuffer1.append("arrays".toCharArray());
stringBuffer1.append(2000L);
stringBuffer1.append("string");
stringBuffer1.append(stringBuffer3);
stringBuffer1.append(stringBuffer4);
stringBuffer1.append(new Object());
System.out.println(stringBuffer1);
System.out.println(stringBuffer1.length());
System.out.println(stringBuffer1.capacity());
stringBuffer1 = null;
System.out.println(stringBuffer1);
/**
* insert
*/
stringBuffer3 = stringBuffer3.insert(0,'h');
System.out.println(stringBuffer3);
stringBuffer3 = stringBuffer3.insert(1,1);
System.out.println(stringBuffer3);
stringBuffer3 = stringBuffer3.insert(2,2000L);
System.out.println(stringBuffer3);
stringBuffer3.insert(0,3.14F);
System.out.println(stringBuffer3);
stringBuffer3.insert(0,false);
System.out.println(stringBuffer3);
stringBuffer3.insert(0,"mystring".toCharArray());
System.out.println(stringBuffer3);
stringBuffer3.insert(0,stringBuffer4);
System.out.println(stringBuffer3);
stringBuffer3.insert(0,new Object());
System.out.println(stringBuffer3);
stringBuffer3.insert(0,"zyxzyx".toCharArray(),0,3);
System.out.println(stringBuffer3);
stringBuffer3.insert(0,stringBuffer4,4,5);
System.out.println(stringBuffer3);
/**
* delete
*/
CharSequence s3sub = stringBuffer3.subSequence(stringBuffer3.length()-10,stringBuffer3.length());
System.out.println(s3sub.toString());
stringBuffer3.deleteCharAt(0);
System.out.println(stringBuffer3);
/**
* 查 改
*/
stringBuffer3.setCharAt(0,'Z');
System.out.println(stringBuffer3);
int len = stringBuffer3.length();
System.out.println(len);
int cap = stringBuffer3.capacity();
System.out.println(cap);
stringBuffer3.trimToSize();
System.out.println(stringBuffer3.capacity() + " " + stringBuffer3.length());
char ch = stringBuffer3.charAt(0);
System.out.println(ch);
String string = stringBuffer3.substring(stringBuffer3.length()-"helloworld".length());
System.out.println(string);
String str = stringBuffer3.substring(0,3);
System.out.println(str);
stringBuffer3.reverse();
System.out.println(stringBuffer3);
stringBuffer3.reverse();
System.out.println(stringBuffer3);
int index = stringBuffer3.indexOf("helloworld");
System.out.println(index);
int index1 = stringBuffer3.indexOf("helloworle");
System.out.println(index1);
int index2 = stringBuffer3.indexOf("hello",10);
System.out.println(index2);
stringBuffer3.replace(0,2,"ahpu");
System.out.println(stringBuffer3);
// stringBuffer3.setLength(100);
// System.out.println(stringBuffer3.charAt(99));
System.out.println(stringBuffer3.length());
int lindex = stringBuffer3.lastIndexOf("helloworld");
System.out.println(lindex);
index = stringBuffer3.indexOf("helloworld");
System.out.println(index);
char[] dst = new char[50];
System.out.println(stringBuffer3.length());
System.out.println(stringBuffer3);
stringBuffer3.trimToSize();
System.out.println(stringBuffer3.length());
stringBuffer3.getChars(61,stringBuffer3.length(),dst,0);
System.out.println(dst);
/**
*
*/
int unicode = stringBuffer3.codePointAt(1);
System.out.println(unicode);
int unicode1 = stringBuffer3.codePointBefore(1);
System.out.println(unicode1);
System.out.println(stringBuffer3.length() + " " + stringBuffer3.capacity());
// 这个方法还真不知道有啥用处
int unicode2 = stringBuffer3.offsetByCodePoints(10,-2);
System.out.println(unicode2);
}
}
- 结果
7
16
hi java123.142.78truearrays2000stringhelloworldAHPU&SEUjava.lang.Object@1b6d3586
80
142
null
hhelloworld
h1helloworld
h12000helloworld
3.14h12000helloworld
false3.14h12000helloworld
mystringfalse3.14h12000helloworld
AHPU&SEUmystringfalse3.14h12000helloworld
java.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
&zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
helloworld
zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
Zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
69
110
69 69
Z
helloworld
Zyx
dlrowolleh00021h41.3eslafgnirtsymUES&UPHAc7164554@tcejbO.gnal.avajxyZ
Zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
59
-1
59
ahpuxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
71
61
61
71
ahpuxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
71
helloworld
104
97
71 71
8
面试session
- StringBuffer StringBuilder String 的异同和使用场景?
(1) StringBuffer是线程安全的,StringBuilder在单线程是StringBuilder的替代品,二者方法基本一致,但是StringBuilder是线程不安全的,二者都是可变字符串类;
(2) String是不可变字符串类;