1.String
1.1成员变量
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
String类中常用的两个成员变量value、hash。
- value:字符类型的数组,用来存放我们所保存的字符串,每一个字符串都会被拆开作为字符来进行存储,使用final关键字进行修饰。
- hash:对应字符串的hash值。
compareTo(str)
比较两个字符串的大小,采用的是逐个字符来进行比较(比较ASCII码)。
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
2.StringBuilder
2.1成员变量
char[] value;
int count;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
2.2append(str)
由于底层存放数据的是一个数组,因此每次都需要进行一个扩容的判断。
如果count+str.length()大于当前数组value的长度,就需要进行扩容,每次扩容后的数组长度=原长度*2+2。
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;
}
//每次都需要进行一个扩容的判断。
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
//每次扩容后的数组长度=原长度*2+2。
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.3总结
StringBuilder补充了String只能读不能写的属性,采用对数组扩容的操作,允许程序员对String类型来进行写操作。
3.StringBuffer
3.1成员变量
和StringBuilder一样
3.2常用方法
append(str)
与StringBuilder类似
StringBuffer
区别在于StringBuffer的方法定义上多了一个关键字Synchronized。通过这个关键字,来保证我们对字符串的写操作的线程安全。
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
3.3总结
StringBuffer在Stringbuilder实现了字符串写操作的基础上,又添加了对它的线程安全方面的维护,是通过在方法上添加synchronized关键字来显示的。
- 这样虽然可以保证线程安全,但是也在一定程度上,舍弃了部分性能。
- 但如果一旦涉及多线程,StringBuffer则能更好的保障我们的线程安全。
总结
对于三者使⽤的总结:
- 操作少量的数据: 适⽤ String
- 单线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuilder
- 多线程操作字符串缓冲区下操作⼤量数据: 适⽤ StringBuffer