Article Directory
- 1. StringBuffer
- 1.1 source code analysis
- 1.1.1 Constructor
- 1. Empty StringBuffer object configuration
- 2. StringBuffer object size specified configuration
- 3. The configuration of the specified initial string StringBuffer object
- 4. The configuration of the specified initial string StringBuffer object
- 1.1.2 The basic method
- 1. Adding character welfare
- 2. Remove the string
- 3. Obtain the part of the string
- 4. Insert Character
- 5. Get subscripting
- 6. Flip string
- Capacity length and character character array 7.
- 1.1.3 StringBuffer summary
- 2. StringBuilder
StringBuffer and StringBuilder are two often used to do string manipulation classes, people usually know StringBuffer is thread-safe, StringBuilder is not thread-safe, but for its internal source did not do too much analysis, we analyze two those differences and their advantages and disadvantages source.
The starting point of this paper is to proceed from the source code, detailed analysis of the difference between the two, both general conclusions about before has written an article summary: String, StringBuffer and StringBuilder difference
1. StringBuffer
Overall String, StringBuffer, StringBuilder class structure between three classes:
the above class structure in FIG, either directly or indirectly dependent on dependency, and the StringBuffer StringBuilder Appendable and interfaces are based CharSequence basis function expansion down to do, because string itself are not changed, and the StringBuffer StringBuilder order to more convenient and efficient operation of the string, the string operations to achieve many of the features, such as appending the string, the string is inserted, and so replacement string.
1.1 source code analysis
According to the above structure analysis StringBuffer class inherited the main abstract class and interface CharSequence AbstractStringBuilder, which provides a method of operation of some primary AbstractStringBuilder string, can be divided into functionally graded appending the string, delete characters, replacing the characters, inserting characters, the character indexes acquired string flips, the series methods are the core of the operating method of the string, and the methods to achieve CharSequence interface primarily get string length, to obtain an index of the character.
Note: All methods are thread-safe, because each method are modified with the synchronized keyword, the more weight class belongs to a lock, the lock according to the characteristics, performance is bound to be lower.
StringBuffer whole property inherited from AbstractStringBuilder, while AbstractStringBuilder underlying character array is used to store characters.
- The use of an array of characters stored in the string value
char[] value;
- count the number of characters in the real value stored in the array
int count;
According to the following function point source comb
1.1.1 Constructor
1. Empty StringBuffer object configuration
The method is mainly AbstractStringBuilder constructor call parent class, to establish a string buffer sequence does not comprise any string, the default buffer size is created 16
StringBuffer.java
public StringBuffer() {
super(16);
}
AbstractStringBuilder.java
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
2. StringBuffer object size specified configuration
Create a does not contain any string of StringBuffer object, given a particular string buffer size, and the parent class's method is similar to the call by the super ().
public StringBuffer(int capacity) {
super(capacity);
}
3. The configuration of the specified initial string StringBuffer object
The specific string objects StringBuffer object configured to, create the default size of argument string length StringBuffer +16
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
Which by append () method to store the string to the original array, note that this method coupled with the synchronized keyword, by locking way to ensure the safety of this method among multiple threads , and the internal implementation method is by the parent class AbstractStringBuilder append () method. From here you can see the importance of AbstractStringBuilder basically is the core method of StringBuffer class.
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
Call append parent class ()
// 该方法是父类AbstractStringBuilder的共用方法
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
// 用于数组长度的扩展
ensureCapacityInternal(count + len);
// 将字符串str追加到value字符数组后
str.getChars(0, len, value, count);
count += len;
return this;
}
Array expansion method to analyze:
// 数组扩展的方法
// 该方法是ensureCapacity的非同步版本
// 主要目的将数组扩展至minimumCapacity,主要是利用数组复制的方式
private void ensureCapacityInternal(int minimumCapacity) {
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,newCapacity(minimumCapacity));
}
}
/**
* 扩展数组大小的思路
* 1. 判断参数中的minCapacity和(2*nowCapacity+2) = newCapacity的大小
* 2. 如果newCapacity < minCapacity,则将数组扩展为minCapacity
* 3. 如果newCapacity > minCapacity,则将数组扩展为2 * nowCapacity + 2
* 4. 校验最新扩容的大小,至少不能比Integer.MAX_VALUE大
* @param minCapacity
* @return
*/
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;
}
/**
* 校验最新扩容的大小,防止数据溢出
* @param minCapacity
* @return
*/
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) {
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
4. The configuration of the specified initial string StringBuffer object
String length sequence of characters into a string configured, the default size parameters created StringBuffer +16
specific extension length of the array and construction methods analogous 3
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
1.1.2 The basic method
A method in accordance with the basic function will be to distinguish between the various methods, for controlling the profile analysis, each feature is only one method of analysis.
1. Adding character welfare
Source code is available in a variety of ways append strings, but overall similar, but different processing request parameters only, now only be analyzed for the most common request parameters Object
/**
* 追加字符串
* 该方法继承于AbstractStringBuilder
* 思路:
* 1. 将参数做强制类型转化为String,再通过父类AbstractStringBuilder的append()方法追加字符串
* @param obj an {@code Object}.
* @return
*/
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
// 调用父类的append()方法追加字符串
super.append(String.valueOf(obj));
return this;
}
2. Remove the string
Delete character within the specified range of indices, there is a method to delete the specified index character, consistent whole idea.
/**
* @param start 开始的下标索引
* @param end 结束的下标索引
* @return
*/
@Override
public synchronized StringBuffer delete(int start, int end) {
toStringCache = null;
// 通过调用父类的删除字符串方法
super.delete(start, end);
return this;
}
/**
* 删除字符序列中一部分
* 思路:
* 1. 前面的都是一些参数的校验,比如检查收尾索引是否得当
* 2. 通过数组复制的方式删除元素
* @param start
* @param end
* @return
*/
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;
}
3. Obtain the part of the string
/**
* 获取字符串的一部分
* @param start 开始索引
* @param end 结束索引
* @return
*/
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
/**
* 获取字符串一部分
* 前面是参数的校验,真正的思路是通过String的构造方法,构造出一个新的字符串
* @param start
* @param end
* @return
*/
public String substring(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
throw new StringIndexOutOfBoundsException(end);
if (start > end)
throw new StringIndexOutOfBoundsException(end - start);
return new String(value, start, end - start);
}
4. Insert Character
Although there are many methods, but only one analysis method, with a way to understand the idea of the entire insert.
/**
* 将字符串插入到元字符串中
* @param offset 开始插入的索引下标
* @param obj 插入的元素
* @return
*/
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
// 调用父类的insert()方法
super.insert(offset, String.valueOf(obj));
return this;
}
/**
* 将字符串插入的原字符索引中
* 思路:
* 1. 扩容
* 2. 复制数组的方式扩展字符数组
* @param offset 开始索引
* @param str 插入的字符串
* @return
*/
public AbstractStringBuilder insert(int offset, String str) {
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
if (str == null)
str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
str.getChars(value, offset);
count += len;
return this;
}
5. Get subscripting
Get string str start position in the original string, the method asynchronous method.
In this method, a multi-layer calls, StringBuffer -> AbstractStringBuilder -> String
@Override
public int indexOf(String str) {
return super.indexOf(str);
}
/**
* 该方法主要用于String、StringBuffer中的搜索使用,
* @param source 被搜索的字符串
* @param sourceOffset 被搜索字符的下标
* @param sourceCount 被搜索字符串的总字符数
* @param target 搜索的字符串
* @param targetOffset 搜索字符串下标
* @param targetCount 搜索字符串总字符数
* @param fromIndex 开始搜索的下标
* @return 返回目标字符串的起始下标,如果没有则返回-1
*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount);
/**
* 整体思路:通过双层循环方式寻找目标字符串的开始及结束
*/
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
6. Flip string
Source in accordance with the analysis, the time complexity of the process itself is O (log2N)
/**
* 字符串翻转
* @return
*/
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
// 通过调用父类的字符串翻转方法
super.reverse();
return this;
}
/**
* 翻转字符串
* 整体的时间复杂度:O(log2N)
* @return
*/
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}
Capacity length and character character array 7.
See the source code provides two methods length () and capacity () method, the former is the number of characters get real StringBuffer object storage, the real capacity of the array StringBuffer object of the latter acquired.
/**
* 获取StringBuffer对象字符串的总长度
* @return
*/
@Override
public synchronized int length() {
return count;
}
/**
* 表示字符数组中的容量,一般该方法获取的值>=length()获取的值
* @return
*/
@Override
public synchronized int capacity() {
return value.length;
}
example:
public class TestStringBuffer {
public static void main(String[] args) {
// 该构造方法会默认创建长度为26的字符数组
StringBuffer s = new StringBuffer("helloWorld");
System.out.println(s.length()); // 10
System.out.println(s.capacity()); // 26
}
}
1.1.3 StringBuffer summary
You can see from the above method, the method in this class are basically adding a thread-safe multi-thread between the Synchronized keyword for guarantee.
2. StringBuilder
This article does not do a detailed analysis of the source code, because the code itself and StringBuffer similar, but each method has no StringBuilder plus Synchronized, although the loss of synchronization features, but greatly improved performance, the frequency of use is also generally larger than StringBuffer.