Android(java):StringBuffer StringBulider区别
来源:互联网 发布:mysql数据备份方案 编辑:程序博客网 时间:2024/05/16 05:48
java数组复制 System.copyarray()方法
System.copyarray()方法可以用来复制数组,其格式是:
System.arraycopy(Object src, int src_position, Object dst, int dst_position, int length)
它将数组从src 复制到dst,复制的位置是src 的第src_position 个元素到dst 的第dst_position
位置,复制元素的个数为length。
注意:该方法只复制元素。如果数组元素是引用型变量,则只复制引用,不复制对象
实体。
StringBuilder 字符串变量(非线程安全)
String 类型和 StringBuffer 、StringBuilder 类型的主要性能区别其实在于 String 是不可变的对象,而后俩者都是可变的。
来看看 StringBuffer类源码定义:
- public finalclass StringBuffer
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
- public StringBuffer() {
- super(16);
- }
- public StringBuffer(int capacity) {
- super(capacity);
- }
- <STRONG>
- public final class StringBuffer
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
- public StringBuffer() {
- super(16);
- }
- public StringBuffer(int capacity) {
- super(capacity);
- }
- </STRONG>
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ public StringBuffer() {super(16); } public StringBuffer(int capacity) {super(capacity); }
上例代码我们发现 StringBuffer 继承了 AbstractStringBuilder抽象类。包括构造方法的实现,都是父类提供的。
然后,我们打开 StringBuilder源码定义:
- public finalclass StringBuilder
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
- public StringBuilder() {
- super(16);
- }
- public StringBuilder(int capacity) {
- super(capacity);
- }
- <STRONG>public final class StringBuilder
- extends AbstractStringBuilder
- implements java.io.Serializable, CharSequence
- {
- public StringBuilder() {
- super(16);
- }
- public StringBuilder(int capacity) {
- super(capacity);
- }
- </STRONG>
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ public StringBuilder() {super(16); } public StringBuilder(int capacity) {super(capacity); }
我们发现两者都继承了AbstractStringBuilder抽象类。且构造方法都调用父类实现。
我们接着看两者append方法实现:
先看StringBuffer的:
- public synchronized StringBuffer append(Object obj) {
- super.append(String.valueOf(obj));
- return this;
- }
- public synchronized StringBuffer append(String str) {
- super.append(str);
- return this;
- }
- //...
- <STRONG>
- public synchronized StringBuffer append(Object obj) {
- super.append(String.valueOf(obj));
- return this;
- }
- public synchronized StringBuffer append(String str) {
- super.append(str);
- return this;
- }
- //...
- </STRONG>
public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; } public synchronized StringBuffer append(String str) { super.append(str); return this; } //...
再看StringBuilder的:
- public StringBuilder append(Object obj) {
- return append(String.valueOf(obj));
- }
- public StringBuilder append(String str) {
- super.append(str);
- return this;
- }
- //...
- <STRONG>
- public StringBuilder append(Object obj) {
- return append(String.valueOf(obj));
- }
- public StringBuilder append(String str) {
- super.append(str);
- return this;
- }
- //...
- </STRONG>
public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } public StringBuilder append(String str) { super.append(str); return this; } //...
对比上面两段源码 我们发现 StirngBuffer 和StringBuilder的 append实现都是调用父类实现的。唯一不同的是 StringBuffer是线程安全的,方法中多了synchronized ,而StringBuilder 是非线程安全的。
我们看下父类AbstractStringBuilder 定义 及 append 实现:
- abstract class AbstractStringBuilderimplements Appendable, CharSequence {
- //底层与String类一样都是 char类型数组。
- char value[];
- //字符串长度
- int count;
- AbstractStringBuilder() {
- }
- AbstractStringBuilder(int capacity) {
- value = new char[capacity];
- }
- <STRONG>abstract class AbstractStringBuilder implements Appendable, CharSequence {
- //底层与String类一样都是 char类型数组。
- char value[];
- //字符串长度
- int count;
- AbstractStringBuilder() {
- }
- AbstractStringBuilder(int capacity) {
- value = new char[capacity];
- }
- </STRONG>
abstract class AbstractStringBuilder implements Appendable, CharSequence { //底层与String类一样都是 char类型数组。 char value[]; //字符串长度 int count; AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; }
- public AbstractStringBuilder append(Object obj) {
- return append(String.valueOf(obj));
- }
- public AbstractStringBuilder append(String str) {
- //对于str==null的
- if (str == null) str ="null";
- int len = str.length();
- if (len == 0)returnthis;
- //新的字符串长度
- int newCount = count + len;
- if (newCount > value.length)
- //当新的字符串长度比原先数组长度大时,需要对char 数组扩容。
- expandCapacity(newCount);
- //将新添的数据追加到char类型数组中。
- str.getChars(0, len, value, count);
- count = newCount;
- return this;
- }
- //数组扩容
- void expandCapacity(int minimumCapacity) {
- //先扩容成 (原先的长度+1)*2
- int newCapacity = (value.length +1) *2;
- //判断newCapacity值是否满足要求
- //如果新的长度还是不够,则直接取值 minimumCapacity
- if (newCapacity < 0) {
- newCapacity = Integer.MAX_VALUE;
- } else if (minimumCapacity > newCapacity) {
- newCapacity = minimumCapacity;
- }
- char newValue[] = new char[newCapacity];
- //将原先的数据拷贝到新的char 数组中。
- System.arraycopy(value, 0, newValue,0, count);
- value = newValue;
- }
- public void getChars(int srcBegin,int srcEnd,char dst[],int dstBegin) {
- if (srcBegin < 0) {
- throw new StringIndexOutOfBoundsException(srcBegin);
- }
- if (srcEnd > count) {
- throw new StringIndexOutOfBoundsException(srcEnd);
- }
- if (srcBegin > srcEnd) {
- throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
- }
- System.arraycopy(value, offset + srcBegin, dst, dstBegin,
- srcEnd - srcBegin);
- }
StringBuffer与StringBuilder是java.lang包下被大家熟知的两个类。其异同为:一、长度都是可扩充的;二、StringBuffer是线程安全的,StringBuilder是线程不安全的。那么他们的长度是如何实现动态扩充以及StringBuffer的线程安全是如何实现的呢?通过“深度”阅读它们的源代码,最终弄明白其中的缘由。
正文
首先上一张StringBuffer和StringBuilder类结构图:
抽象类AbstractStringBuilder(也是核心实现类)实现了Appendable和CharSequence两个接口;StringBuffer与StringBuilder统统继承自AbstractStringBuilder,并且实现了java.io.Serializable和CharSequence接口。
下面简单描述下这几个接口所起到的作用(引用自中文api)。
- Appendable:能够被添加 char 序列和值的对象。如果某个类的实例打算接收java.util.Formatter 的格式化输出,那么该类必须实现 Appendable 接口
- 。要添加的字符应该是有效的 Unicode 字符,正如 Unicode Character Representation 中描述的那样。注意,增补字符可能由多个 16 位char 值组成
- CharSequence:CharSequence 是 char 值的一个可读序列。此接口对许多不同种类的 char 序列提供统一的只读访问。char 值表示 Basic Multilingual Plane (BMP) 或代理项中的一个字符。有关详细信息,请参阅Unicode 字符表示形式。此接口不修改equals 和hashCode 方法的常规协定。因此,通常未定义比较实现 CharSequence 的两个对象的结果。每个对象都可以通过一个不同的类实现,而且不能保证每个类能够测试其实例与其他类的实例的相等性。因此,使用任意 CharSequence 实例作为集合中的元素或映射中的键是不合适的。
- Serializable:类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
- AbstractStringBuilde
- r这个抽象类提供了StringBuffer和StringBuilder绝大部分的实现。在AbstractStringBuilder的描述中说:如果去掉线程安全,那么StringBuffer和StringBuilder是完全一致的。从实现的角度来说,StringBuffer所有方法(构造方法除外,因为没有必要)签名中都使用synchronized限定,也就是所有的方法都是同步的。
eg.StringBuffer中replace()方法
1
public
synchronized
StringBuffer replace(
int
start,
int
end, String str) {
2
super
.replace(start, end, str);
3
return
this
;
4
}
StringBuilder中replace():
1
public
StringBuilder replace(
int
start,
int
end, String str) {
2
super
.replace(start, end, str);
3
return
this
;
4
}
区别仅仅在方法签名上是否有synchronized。
另外需要稍稍注意的问题是:StringBuffer同步只同步目标,比如:sb.append("i am not synchronized"),sb是同步的,而其中的参数未必是同步的。
而它们两个可扩展长度则是通过ensureCapacity(int minimumCapacity)来验证当前长度是否小于参数minimumCapacity,如果成立则进行分配空间。分配新空间的步长为(当前长度+1)的两倍。
实现如下:
01
public
void
ensureCapacity(
int
minimumCapacity) {
02
if
(minimumCapacity > value.length) {
03
expandCapacity(minimumCapacity);
04
}
05
}
06
void
expandCapacity(
int
minimumCapacity) {
07
int
newCapacity = (value.length +
1
) *
2
;
08
if
(newCapacity <
0
) {
09
newCapacity = Integer.MAX_VALUE;
10
}
else
if
(minimumCapacity > newCapacity) {
11
newCapacity = minimumCapacity;
12
}
13
value = Arrays.copyOf(value, newCapacity);
14
}
如果新的长度小于0(溢出了),则使用Integer的最大值作为长度。
另外,在阅读源码的过程中,发现两个有趣的问题,下面一一道来。
第一个,就是reverse的实现。其实我是第一次看StringBuilder和StringBuffer的源码,这里面的reverse的实现是我所知道的java中的最高效的实现,没有之一。
上源码,再做解释:
01
public
AbstractStringBuilder reverse() {
02
boolean
hasSurrogate =
false
;
03
int
n = count -
1
;
04
for
(
int
j = (n-
1
) >>
1
; j >=
0
; --j) {
05
char
temp = value[j];
06
char
temp2 = value[n - j];
07
if
(!hasSurrogate) {
08
hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
09
|| (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
10
}
11
value[j] = temp2;
12
value[n - j] = temp;
13
}
14
if
(hasSurrogate) {
15
// Reverse back all valid surrogate pairs
16
for
(
int
i =
0
; i < count -
1
; i++) {
17
char
c2 = value[i];
18
if
(Character.isLowSurrogate(c2)) {
19
char
c1 = value[i +
1
];
20
if
(Character.isHighSurrogate(c1)) {
21
value[i++] = c1;
22
value[i] = c2;
23
}
24
}
25
}
26
}
27
return
this
;
28
}
reverse分成两个部分:前面一个循环与后面的判断。
首先地一个循环很高效,循环次数为长度(count)的一半,而且使用>>位移运算,交换数组value[j]与value[n-j]的值。这里一是循环次数少,而是使用最高效的位移运算所以说这个reverse很高效。在反转过程中还完成了一件事:就是为hasSurrogate赋值。赋值的依据就是value[j]与value[n-j]两个字符时候有一个在\uD800和\uDFFF之间,如果有则赋值为true。
- <STRONG>
- public AbstractStringBuilder append(Object obj) {
- return append(String.valueOf(obj));
- }
- public AbstractStringBuilder append(String str) {
- //对于str==null的
- if (str == null) str = "null";
- int len = str.length();
- if (len == 0) return this;
- //新的字符串长度
- int newCount = count + len;
- if (newCount > value.length)
- //当新的字符串长度比原先数组长度大时,需要对char 数组扩容。
- expandCapacity(newCount);
- //将新添的数据追加到char类型数组中。
- str.getChars(0, len, value, count);
- count = newCount;
- return this;
- }
- //数组扩容
- void expandCapacity(int minimumCapacity) {
- //先扩容成 (原先的长度+1)*2
- int newCapacity = (value.length + 1) * 2;
- //判断newCapacity值是否满足要求
- //如果新的长度还是不够,则直接取值 minimumCapacity
- if (newCapacity < 0) {
- newCapacity = Integer.MAX_VALUE;
- } else if (minimumCapacity > newCapacity) {
- newCapacity = minimumCapacity;
- }
- char newValue[] = new char[newCapacity];
- //将原先的数据拷贝到新的char 数组中。
- System.arraycopy(value, 0, newValue, 0, count);
- value = newValue;
- }
- public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
- if (srcBegin < 0) {
- throw new StringIndexOutOfBoundsException(srcBegin);
- }
- if (srcEnd > count) {
- throw new StringIndexOutOfBoundsException(srcEnd);
- }
- if (srcBegin > srcEnd) {
- throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
- }
- System.arraycopy(value, offset + srcBegin, dst, dstBegin,
- srcEnd - srcBegin);
- }
- </STRONG>
public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } public AbstractStringBuilder append(String str) { //对于str==null的 if (str == null) str = "null"; int len = str.length(); if (len == 0) return this; //新的字符串长度 int newCount = count + len; if (newCount > value.length) //当新的字符串长度比原先数组长度大时,需要对char 数组扩容。 expandCapacity(newCount); //将新添的数据追加到char类型数组中。 str.getChars(0, len, value, count); count = newCount; return this; } //数组扩容 void expandCapacity(int minimumCapacity) { //先扩容成 (原先的长度+1)*2 int newCapacity = (value.length + 1) * 2; //判断newCapacity值是否满足要求 //如果新的长度还是不够,则直接取值 minimumCapacity if (newCapacity < 0) { newCapacity = Integer.MAX_VALUE; } else if (minimumCapacity > newCapacity) { newCapacity = minimumCapacity; } char newValue[] = new char[newCapacity]; //将原先的数据拷贝到新的char 数组中。 System.arraycopy(value, 0, newValue, 0, count); value = newValue; } public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } if (srcEnd > count) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } System.arraycopy(value, offset + srcBegin, dst, dstBegin, srcEnd - srcBegin); }
- Android(java):StringBuffer StringBulider区别
- java StringBuffer StringBulider 区别
- stringbuffer与stringbulider区别
- String StringBuffer StringBulider 区别
- String,Stringbuffer,StringBulider区别
- String,StringBuffer,StringBulider的区别
- String,StringBuffer,StringBulider的区别
- String StringBuffer StringBulider的区别
- String、StringBulider、StringBuffer 的区别
- String,StringBulider,StringBuffer的区别
- StringBuffer 和StringBulider的区别
- String、StringBulider、StringBuffer的区别
- String,StringBuffer,StringBulider的区别
- String ,StringBuffer ,StringBulider效率和区别
- 黑马程序员-----String,StringBuffer,StringBulider区别
- String StringBuffer 和 StringBulider的区别
- String、StringBuffer与StringBulider之间区别
- String,StringBuffer,StringBulider区别与联系
- 第十二周项目-1函数运用 当年第几天
- iis 配置httpd.ini 伪静态状态为未知
- linux下代码走查工具介绍---splint
- 关于linux环境下修改mysql字符编码的问题
- 路由器端口映射设置方法图解
- Android(java):StringBuffer StringBulider区别
- Ubuntu android 开发环境搭建之eclipse篇
- android:duplicateParentState属性解释
- struts2.0、hibernate3、spring2.5框架整合流程实例
- 图像的配准及在VC++中实现
- CSDN-FENG 2013.11
- java中重载与重写的区别
- 计算运行耗时
- PHP算法 参数组合,多个分类不同组合列表