本文共 11716 字,大约阅读时间需要 39 分钟。
先看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: *
* 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.charAt(k)-anotherString.charAt(k) ** * @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; }* this.length()-anotherString.length() *
原理是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: *
* * @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: ** dstBegin + (srcEnd-srcBegin) - 1 *
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; }
其实这些都很简单,看看源码就可以知道原理,可以简化使用,加快效率。
转载地址:http://oslvd.baihongyu.com/