java清空StringBuffer的方法分析
方法汇总
方法1:指向新的内存空间。即通过赋予新的实例的方式,使引用执行新的空的内存空间。
StringBuffer stringBuffer = new StringBuffer();
stringBuffer = new StringBuffer(); //通过赋值让引用执行新的内存空间
方法2:删除全部字符。即通过delete方法,从开始位删除到结尾位。
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("Hello world!");
int length = stringBuffer.length();
stringBuffer.delete(0, length); // 删除stringBuffer保存的全部字符
方法3:设置长度为0。StringBuffer内部是通过字符数组的形式来保存内容的。StringBuffer有两个从父类AbstractStringBuilder中继承的成员属性,分别是用于存储内存的字符数组char[] value,和计算数组value中使用量的int count。设置长度为0就是通过setLength方法将count置零,让新传入的内容从value的0位置开始存储。
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("Hello world!");
stringBuffer.setLength(0); //设置stringBuffer的长度为0
方法对比
对比角度1:源码分析
1、指向新的内存空间:
这种方式需要创建新的内存。从开销角度,是new一个实例的开销;但是从对JVM的影响的角度,丢弃原本的实例去执行新创建的实例的做法,会加速gc的到来,并不推荐。
2、删除全部字符:
查看源码:
@Override
public synchronized StringBuffer delete(int start, int end) {toStringCache = null;super.delete(start, end);return this;
}
可以看到,StringBuffer的delete方法是通过调用父类的delete方法来实现的。查看父类AbstractStringBuilder的delete方法:
public AbstractStringBuilder delete(int start, int end) {if (start < 0)throw new StringIndexOutOfBoundsException(start);if (end > count)end = count;if (start > end)throw new StringIndexOutOfBoundsException();int len = end - start;if (len > 0) {System.arraycopy(value, start+len, value, start, count-end);count -= len;}return this;
}
通过源码可以看出,传入合法的start和end参数的情况下,需要执行四次判断操作、一次减法和赋值操作,然后去调用System的arraycopy方法。查看System的arraycopy方法可以发现,这是一个本地方法。本地方法的调用,涉及到初次调用时本地方法的加载、java参数于本地方法参数的转换等的开销,以及由于JVM的GC无法管理本地方法内存,本地方法的使用者需要自行关注内存的创建、使用和销毁等问题,同时本地方法也无法享受JVM优化的成功。所以在涉及到本地方法调用的时候应该谨慎。System的arraycopy方法:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
3、设置长度为0:
查看setLength方法的源码:
public class StringBufferClearer {public static void main(String[] args) {StringBuffer content = new StringBuffer();for (int i = 0; i < 10; i++) {content.append("Hello, world!");}String data = content.toString();int count = 10000 * 10000;// test way 1:long timeBegin1 = System.currentTimeMillis();for (int i = 0; i < count; i++) {StringBuffer stringBuffer = new StringBuffer();stringBuffer.append(data);stringBuffer = new StringBuffer();}System.out.println("new StringBuffer() time cost: " + (System.currentTimeMillis() - timeBegin1));// test way 2:long timeBegin2 = System.currentTimeMillis();for (int i = 0; i < count; i++) {StringBuffer stringBuffer = new StringBuffer();stringBuffer.append(data);stringBuffer.delete(0, stringBuffer.length());}System.out.println("delete time cost: " + (System.currentTimeMillis() - timeBegin2));// test way 3:long timeBegin3 = System.currentTimeMillis();for (int i = 0; i < count; i++) {StringBuffer stringBuffer = new StringBuffer();stringBuffer.append(data);stringBuffer.setLength(0);}System.out.println("setLength time cost: " + (System.currentTimeMillis() - timeBegin3));}
}
测试结果:
new StringBuffer() time cost: 6482
delete time cost: 5238
setLength time cost: 5096
总结
根据测试结果,性能确实和预料基本相似。所以,推荐优先使用setLength方法设置长度为0。当然,delete方法开销的差距也并不大。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
