先看String,上源码
public final class String
implements java.io.Serializable, Comparable, CharSequence {
/** The value is used for character storage. */
private final char value[];
String的本质就是char数组,JDK9之后改为byte数组了;是线程安全的原因,final修饰。
String是final class不能被继承。
String实现了Comparable接口可以直接比较
/**
* Compares two strings lexicographically.
* The comparison is based on the Unicode value of each character in
* the strings. The character sequence represented by this
* {@code String} object is compared lexicographically to the
* character sequence represented by the argument string. The result is
* a negative integer if this {@code String} object
* lexicographically precedes the argument string. The result is a
* positive integer if this {@code String} object lexicographically
* follows the argument string. The result is zero if the strings
* are equal; {@code compareTo} returns {@code 0} exactly when
* the {@link #equals(Object)} method would return {@code true}.
*
* This is the definition of lexicographic ordering. If two strings are
* different, then either they have different characters at some index
* that is a valid index for both strings, or their lengths are different,
* or both. If they have different characters at one or more index
* positions, let k be the smallest such index; then the string
* whose character at position k has the smaller value, as
* determined by using the < operator, lexicographically precedes the
* other string. In this case, {@code compareTo} returns the
* difference of the two character values at position {@code k} in
* the two string -- that is, the value:
*
* this.charAt(k)-anotherString.charAt(k)
*
* If there is no index position at which they differ, then the shorter
* string lexicographically precedes the longer string. In this case,
* {@code compareTo} returns the difference of the lengths of the
* strings -- that is, the value:
*
* this.length()-anotherString.length()
*
*
* @param anotherString the {@code String} to be compared.
* @return the value {@code 0} if the argument string is equal to
* this string; a value less than {@code 0} if this string
* is lexicographically less than the string argument; and a
* value greater than {@code 0} if this string is
* lexicographically greater than the string argument.
*/
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;
}
原理是char循环,以最短的字符串size循环,逐个比较ASCII码,对于number类型的String,不能使用此方法比较,比如-1与-6,按照这种比对方式,-6>-1这显然不是我们想要的。
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
*/
private transient char[] toStringCache;
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
本质还是char数组,但是是可变的。看本质append方法
/**
* Appends the specified {@code CharSequence} to this
* sequence.
*
* The characters of the {@code CharSequence} argument are appended,
* in order, increasing the length of this sequence by the length of the
* argument.
*
*
The result of this method is exactly the same as if it were an
* invocation of this.append(s, 0, s.length());
*
*
This method synchronizes on {@code this}, the destination
* object, but does not synchronize on the source ({@code s}).
*
*
If {@code s} is {@code null}, then the four characters
* {@code "null"} are appended.
*
* @param s the {@code CharSequence} to append.
* @return a reference to this object.
* @since 1.5
*/
@Override
public synchronized StringBuffer append(CharSequence s) {
toStringCache = null;
super.append(s);
return this;
}
线程安全的核心synchronized,深入了解append方法
super.append(s);
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
}
/**
* Appends the specified string to this character sequence.
*
* 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.
*
* Let n be the length of this character sequence just prior to
* execution of the {@code append} method. Then the character at
* index k in the new character sequence is equal to the character
* at index k in the old character sequence, if k is less
* than n; otherwise, it is equal to the character at index
* k-n in the argument {@code str}.
*
* @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;
}
//扩容数组->新建数组,拷贝原数组至新数组
ensureCapacityInternal(count + len);
/**
* 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));
}
}
/**
* Copies the specified array, truncating or padding with null characters (if necessary)
* so the copy has the specified length. For all indices that are valid
* in both the original array and the copy, the two arrays will contain
* identical values. For any indices that are valid in the copy but not
* the original, the copy will contain '\\u000'. Such indices
* will exist if and only if the specified length is greater than that of
* the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with null characters
* to obtain the specified length
* @throws NegativeArraySizeException if newLength is negative
* @throws NullPointerException if original is null
* @since 1.6
*/
public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
本质是调用native复制数组
str.getChars(0, len, value, count);
/**
* Copies characters from this string into the destination character
* array.
*
* The first character to be copied is at index {@code srcBegin};
* the last character to be copied is at index {@code srcEnd-1}
* (thus the total number of characters to be copied is
* {@code srcEnd-srcBegin}). The characters are copied into the
* subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
*
* dstBegin + (srcEnd-srcBegin) - 1
*
*
* @param srcBegin index of the first character in the string
* to copy.
* @param srcEnd index after the last character in the string
* to copy.
* @param dst the destination array.
* @param dstBegin the start offset in the destination array.
* @exception IndexOutOfBoundsException If any of the following
* is true:
* - {@code srcBegin} is negative.
*
- {@code srcBegin} is greater than {@code srcEnd}
*
- {@code srcEnd} is greater than the length of this
* string
*
- {@code dstBegin} is negative
*
- {@code dstBegin+(srcEnd-srcBegin)} is larger than
* {@code dst.length}
*/
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
//数组拷贝
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
跟StringBuffer一样,只是没有同步罢了
public final class StringJoiner {
private final String prefix;
private final String delimiter;
private final String suffix;
/*
* StringBuilder value -- at any time, the characters constructed from the
* prefix, the added element separated by the delimiter, but without the
* suffix, so that we can more easily add elements without having to jigger
* the suffix each time.
*/
private StringBuilder value;
/*
* By default, the string consisting of prefix+suffix, returned by
* toString(), or properties of value, when no elements have yet been added,
* i.e. when it is empty. This may be overridden by the user to be some
* other value including the empty String.
*/
private String emptyValue;
可以看出本质是StringBuilder,封装了分隔符,前后缀,便于我们append
初始化前后缀,在构造的时候
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
Objects.requireNonNull(prefix, "The prefix must not be null");
Objects.requireNonNull(delimiter, "The delimiter must not be null");
Objects.requireNonNull(suffix, "The suffix must not be null");
// make defensive copies of arguments
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
this.emptyValue = this.prefix + this.suffix;
}
append的时候自动加入分隔符
private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
} else {
value = new StringBuilder().append(prefix);
}
return value;
}
其实这些都很简单,看看源码就可以知道原理,可以简化使用,加快效率。