Java基础(四) StringBuffer、StringBuilder原理浅析
StringBuilder与StringBuffer作用就是用来处理字符串,但String类本身也具备很多方法可以用来处理字符串,那么为什么还要引入这两个类呢?
关于String的讲解请看Java基础(三) String深度解析
首先看下面的例子
public static void main(String[] args) {
String str0 = "hel,lo,wor,l,d";
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++){
str0 += i;
}
System.out.println(System.currentTimeMillis() - start);
StringBuilder sb = new StringBuilder("hel,lo,wor,l,d");
long start1 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++){
sb.append(i);
}
System.out.println(System.currentTimeMillis() - start1);
StringBuffer sbf = new StringBuffer("hel,lo,wor,l,d");
long start2 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++){
sbf.append(i);
}
System.out.println(System.currentTimeMillis() - start2);
}
上述代码中3处循环完成了同样的功能,字符串拼接,执行的结果如下:
36823
3
4
可以看出执行时间差别太大,为了解决String不擅长的大量字符串拼接这种业务场景,引入了StringBuffer和StringBuilder.
首先我们分析一下为什么String在大量字符串拼接这种场景下这么慢?
因为String本身不可变,我们对String的任何操作都会返回一个新的对象,然后当前String变量指向新的对象,而原来的String对象就会被GC回收,那么在循环中就会大量快速的创建新的对象,大量原来的对象会不断的被GC回收,消耗的时间是非常恐怖的,而且内存占用非常大。
下面我们对比了String、StringBuffer与StringBuilder的区别
| String | StringBuffer | StringBuilder |
|---|---|---|
| final修饰,不可继承 | final修饰,不可继承 | final修饰,不可继承 |
| 字符串常量,创建后不可变 | 字符串变量,可动态修改 | 字符串变量,可动态修改 |
| 不存在线程安全问题 | 线程安全,所有public方法由synchronized修改 | 线程不安全 |
| 大量字符串拼接效率最低 | 大量字符串拼接效率非常高 | 大量字符串拼接效率最高 |
StringBuffer与StringBuilder实现非常类似,下面以StringBuilder简单说明一下append()方法基本原理
1. 首先创建一个StringBuilder
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder(100);
StringBuilder对字符串的操作是通过char[]来实现的,通过默认构造器创建的StringBuilder,其内部创建的char[]的默认长度为16,当然可以调用重载的构造器传递初始长度(推荐这样,因为这样可以减少数组扩容次数,提高效率)。
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuilder() {
super(16);
}
2. StringBuilder的append()方法
每次调用append(str)方法时,会首先判断数组长度是否足以添加传递来的字符串
/**
* Appends the specified string to this character sequence.
* <p>
* The characters of the {@code String} argument are appended, in
* order, increasing the length of this sequence by the length of the
* argument. If {@code str} is {@code null}, then the four
* characters {@code "null"} are appended.
*
* @param str a string.
* @return a reference to this object.
*/
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
/**
* For positive values of {@code minimumCapacity}, this method
* behaves like {@code ensureCapacity}, however it is never
* synchronized.
* If {@code minimumCapacity} is non positive due to numeric
* overflow, this method throws {@code OutOfMemoryError}.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
如果传递的字符串长度 + 数组已存放的字符的长度 > 数组的长度,这时就需要进行数据扩容了
/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by the same amount + 2 if
* that suffices.
* Will not return a capacity greater than {@code MAX_ARRAY_SIZE}
* unless the given minimum capacity is greater than that.
*
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero or
* greater than Integer.MAX_VALUE
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
扩容规则如下:默认将数组长度设置为“ (当前数组长度 * 2) + 2”,但如果按此规则扩容后的数组也不足以添加新的字符串,就需要将数组长度设置为“数组内字符长度 + 传递的字符串长度”。
因此假如我们知道拼接的字符串大概长度有100多字符,我们就可以设置初始长度150或200,这样就可以避免或减少数组扩容的次数,从而提高效率。
总结:
本文StringBuffer与StringBuilder的创建,append方法的原理讲解,对比了String、StringBuffer与StringBuilder异同,若有不对之处,请批评指正,谢谢!
Java基础(四) StringBuffer、StringBuilder原理浅析的更多相关文章
- Java基础之Collection与Collections浅析
Java基础之Collection与Collections浅析 一.前言: 位于Java.util包下的Collection与Collections都是Java中重要的工具类,它们都是Java集合框架 ...
- Java基础之多态和泛型浅析
Java基础之多态和泛型浅析 一.前言: 楼主看了许多资料后,算是对多态和泛型有了一些浅显的理解,这里做一简单总结 二.什么是多态? 多态(Polymorphism)按字面的意思就是“多种状态”.在面 ...
- Java基础之String,StringBuilder,StringBuffer
在创建字符串的时候总是习惯性的使用String str = "...";,str = str+"abcd";也有听说过StringBuffer,StringBu ...
- Java学习|String,StringBuffer,StringBuilder?
1 String (1) String的创建机理 由于String在Java世界中使用过于频繁,Java为了避免在一个系统中产生大量的String对象,引入了字符串常量池.其运行机制是:创建一个字 ...
- Java基础 String/StringBuff/StringBuilder 常用操作方法复习/内存分析/三者的效率比较
附:jdk1.8使用IDEA安装.创建.使用JUnit单元测试 笔记总结: /**String 复习 * 1.像C++这样的char arr[]="..." 的方式无法声明Java ...
- java中 String StringBuffer StringBuilder的区别
* String类是不可变类,只要对String进行修改,都会导致新的对象生成. * StringBuffer和StringBuilder都是可变类,任何对字符串的改变都不会产生新的对象. 在实际使用 ...
- Java中String/StringBuffer/StringBuilder区别(转)
1.三者在执行速度方面的比较:StringBuilder > StringBuffer > String 2.String <(StringBuffer,StringBuild ...
- java 基础 四种权限修饰符
/** * Java有四种权限修饰符: * public > protected > (default) > private * 同一个类 YES YES YES YES * 同一个 ...
- Java基础 StringBuffer、StringBuilder原理浅析
StringBuilder与StringBuffer作用就是用来处理字符串,但String类本身也具备很多方法可以用来处理字符串,那么为什么还要引入这两个类呢? 首先看下面的例子 public sta ...
随机推荐
- matlab 神经网络工具箱的实用
0. 其他处理 计时: tic net = train(net, X, y); toc 1. 一个简单的 demo(单层感知器) P = [1, 1, 1, 1, 0, 0, 0, 0; 0, 0, ...
- C#中的并发编程知识二
= 导航 顶部 基本信息 ConcurrentQueue ConcurrentStack ConcurrentBag BlockingCollection ConcurrentDictiona ...
- 纯洁CSS3实现图片墙
预赛 DIV+CSS基金会 CSS3的transform 和 transition说明 主要用于transform的rotate/scale 动画过渡的几个參数(transition-property ...
- ShopNC本地生活o2o网站的源代码,没有域名限制
较前某VIP源代码论坛分享了套ShopNC本地生活o2o站点系统.下载过来却发现根本不能用,所以一直没分享出来.今天咱们这边分享的这套ShopNC本地生活o2o站点源代码,无不论什么的限制,直接ins ...
- [视频]产品营销之拍出好电子产品,Peter Belanger是如何为苹果产品拍照的
Peter Belanger –他就是那些颠覆你想象的苹果产品照片的摄影师.作为旧金山的顶级产品图片设计师的 Peter,他还拥有 eBay, Nike, Pixer 和 Square 等客户. 让我 ...
- [转]更改ejs模板后缀.ejs为.html
三种写法 1,express老写法,3.*已经不支持 app.register('.html', require('ejs')); app.set('view engine', 'ejs'); 2, ...
- XF Grid使用-两行两列-跟WPF不同
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http:/ ...
- 读BeautifulSoup官方文档之与bs有关的对象和属性(1)
自从10号又是5天没更, 是, 我再一次断更... 原因是朋友在搞python, 老问我问题, 我python也是很久没碰了, 于是为了解决他的问题, 我只能重新开始研究python, 为了快速找回感 ...
- WPF绑定到linq表达式
using ClassLibrary;using System;using System.Collections.Generic;using System.Collections.ObjectMode ...
- Win10 如何以管理员身份设置开机自启程序(1)
原文:Win10 如何以管理员身份设置开机自启程序(1) 最近一个项目在win10上部署时遇到问题,即如何设置以管理员身份开机自启.现把解决方法整理如下: 首先,为了进行验证,我编了一个简单的程序te ...