从StringBuilder来看Builder模式
一.角色
二.作用
1.将字符做了缓存,避免了重复的new String对象,造成内存的开销。
2.封装了字符的拼接,和移除方法,不需要关心内部字符串的操作,起到了解耦效果。
三.String代码分析
像常用的substring,replace,concat等方法,均会创建新的对象。
以下来自 openjdk\jdk\src\share\classes\java\lang\String.java
public String substring(int beginIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } int subLen = value.length - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); } public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this; } public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
四.StringBuilder代码分析
以下来自 openjdk\jdk\src\share\classes\java\lang\AbstractStringBuilder.java
abstract class AbstractStringBuilder implements Appendable, CharSequence{ //缓存的字符数组 char[] value; //使用了的字符的数量 int count; AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; } @Override public int length() { return count; } public int capacity() { return value.length; } public void ensureCapacity(int minimumCapacity) { if (minimumCapacity > 0) ensureCapacityInternal(minimumCapacity); } private void ensureCapacityInternal(int minimumCapacity) { //如果目标长度超过了,字符数组的长度,则扩容为原先2倍 if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } private int newCapacity(int minCapacity) { int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; } private int hugeCapacity(int minCapacity) { if (Integer.MAX_VALUE - minCapacity < 0) { // overflow throw new OutOfMemoryError(); } return (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE; } //...... @Override public char charAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); return value[index]; } //追加、 public AbstractStringBuilder append(Object obj) { return append(String.valueOf(obj)); } 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; } public AbstractStringBuilder append(StringBuffer sb) { if (sb == null) return appendNull(); int len = sb.length(); ensureCapacityInternal(count + len); sb.getChars(0, len, value, count); count += len; return this; } //... }
openjdk\jdk\src\share\classes\java\lang\StringBuilder.java
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence { //默认容量为16 public StringBuilder() { super(16); } public StringBuilder(int capacity) { super(capacity); } public StringBuilder(String str) { super(str.length() + 16); append(str); } public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); } @Override public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } @Override public StringBuilder append(String str) { super.append(str); return this; } public StringBuilder append(StringBuffer sb) { super.append(sb); return this; } @Override public StringBuilder append(CharSequence s) { super.append(s); return this; } //....... @Override public StringBuilder append(boolean b) { super.append(b); return this; } @Override public StringBuilder append(char c) { super.append(c); return this; } @Override public StringBuilder append(int i) { super.append(i); return this; } @Override public StringBuilder append(long lng) { super.append(lng); return this; } @Override public StringBuilder append(float f) { super.append(f); return this; } @Override public StringBuilder append(double d) { super.append(d); return this; } //......... }
四.Append方法分析
单个字符直接加1
@Override public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); value[count++] = c; return this; }
public AbstractStringBuilder append(int i) { if (i == Integer.MIN_VALUE) { append("-2147483648"); return this; } int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1 : Integer.stringSize(i); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); Integer.getChars(i, spaceNeeded, value); count = spaceNeeded; return this; }
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; }
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); } //底层调用native方法 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
五.总结
在StringBuilder中,采用了类似Builder模式的设计思路来实现。从而达到了缓存对象,和隐藏和封装构建字符对象的效果。