AbstractStringBuilder是一个抽象类,是StringBuilder和StringBuffer的父类,分析它的源码对StringBuilder和StringBuffer代码的理解有很大的帮助。

先来看看该类的声明:

abstract class AbstractStringBuilder implements Appendable, CharSequence {}

该类实现Appendable和CharSequence接口。

成员变量:

char[] value;//字符数组用来存储字符串
int count;//值是字符串数组被使用的长度。注意,字符数组被使用长度不等于字符数组长度

构造器:

AbstractStringBuilder() {//无参构造器
} AbstractStringBuilder(int capacity) {//带一个int参数构造器,capacity是字符串数组的大小,相当于字符串容器的大小
value = new char[capacity];
}

方法:

//返回字符串实际大小
public int length() {
return count;
}

//返回容器容量
public int capacity() {
return value.length;
}

//确保容器的大小比minimumCapcipty大
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)
ensureCapacityInternal(minimumCapacity);
} private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)//如果minimumCapacity比容器大
expandCapacity(minimumCapacity);//扩容
} void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;//新容量是(原容量大小+1)*2
if (newCapacity - minimumCapacity < 0)//如果扩容后仍然不够minimumCapacity
newCapacity = minimumCapacity;//那么新容量就是minimumCapacity
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);//创建新容器
}

//这个方法是让容器的大小变成跟字符串大小一样
public void trimToSize() {
if (count < value.length) {
value = Arrays.copyOf(value, count);
}
}

//设置字符串的长度,如果比原来长,多出来的部分填充'\0',如果比原来短,截断
public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
ensureCapacityInternal(newLength); if (count < newLength) {
Arrays.fill(value, count, newLength, '\0');
} count = newLength;
}

//返回index位置的字符
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}

//注意下面的append方法,重载的方法很多,支持各种类型参数的append,仅列出部分
//在字符串末尾添加一个字符串,该字符串由obj的toString方法决定
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}

//在字符串末尾添加一个字符串str
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;
}

//在字符串后面添加null字符串
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}

//删除start至end的字符子串,容量不变,字符串长度减少end-start
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;
}
}

//返回start至end的子串
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);
}

//在index位置插入str从offset开始,长度为len的子串
public AbstractStringBuilder insert(int index, char[] str, int offset,
int len)
{
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len);
System.arraycopy(value, index, value, index + len, count - index);
System.arraycopy(str, offset, value, index, len);
count += len;
}

//将字符串的顺序颠倒,如"abc" reverse 成 "cba"
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;
} //...还有其他的方法

可以看到AbstractStringBuilder几乎定义了所有字符串的操作,同时它接受任意类型的拼接,在一个动态数组上操作字符串,对于频繁的字符操作,相比于直接使用String来操作new一个新的String,能提高效率。

java.util.AbstractStringBuilder源码分析的更多相关文章

  1. java.util.HashMap源码分析

    在java jdk8中对HashMap的源码进行了优化,在jdk7中,HashMap处理“碰撞”的时候,都是采用链表来存储,当碰撞的结点很多时,查询时间是O(n). 在jdk8中,HashMap处理“ ...

  2. java.util.Collection源码分析和深度讲解

    写在开头 java.util.Collection 作为Java开发最常用的接口之一,我们经常使用,今天我带大家一起研究一下Collection接口,希望对大家以后的编程以及系统设计能有所帮助,本文所 ...

  3. java.util.Hashtable源码分析

    Hashtable实现一个键值映射的表.任何非null的object可以用作key和value. 为了能存取对象,放在表里的对象必须实现hashCode和equals方法. 一个Hashtable有两 ...

  4. java.util.Dictionary源码分析

    Dictionary是一个抽象类,Hashtable是它的一个子类. 类的声明:/** The <code>Dictionary</code> class is the abs ...

  5. java.util.TreeSet源码分析

    TreeSet是基于TreeMap实现的,元素的顺序取决于元素自身的自然顺序或者在构造时提供的比较器. 对于add,remove,contains操作,保证log(n)的时间复杂度. 因为Set接口的 ...

  6. java.util.TreeMap源码分析

    TreeMap的实现基于红黑树,排列的顺序根据key的大小,或者在创建时提供的比较器,取决于使用哪个构造器. 对于,containsKey,get,put,remove操作,保证时间复杂度为log(n ...

  7. java.util.LinkedList源码分析

    public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, D ...

  8. java.util.ArrayList源码分析

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  9. java.util.HashSet源码分析

    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java. ...

随机推荐

  1. 多线程操作Coredata(转)

    第一步:搭建 Core Data 多线程环境这个问题首先要解决的是搭建 Core Data 多线程环境.Core Data 对并发模式的支持非常完备,NSManagedObjectContext 的指 ...

  2. Android设计模式系列--原型模式

    CV一族,应该很容易理解原型模式的原理,复制,粘贴完后看具体情况是否修改,其实这就是原型模式.从java的角度看,一般使用原型模式有个明显的特点,就是实现cloneable的clone()方法.原型模 ...

  3. Qt 经典出错信息之”Basic XLib functionality test failed!”(Z..z..)

    此完整出错信息是在./configure阶段 Basic XLib functionality test failed! You might need to modify the include an ...

  4. 在WWDC 2014上,没提到的iOS 8 八大新特性

    今天凌晨1点,36氪如约为大家研磨出WWDC 2014全程 "贴身直播"(我不得不佩服牺牲个人时间,熬夜为大家奉上好文的5位氪星人:JasonZheng.WANGJINGYU.pa ...

  5. 【49】了解new_handler的行为

    1.使用operator new无法获取内存时,对于旧式编译器,会返回一个null指针.对于新式编译器,会抛出一个异常. 2.考虑下面的需求,当operator new 无法获取内存时,程序员期望获得 ...

  6. 乐视mysql面试题

      http://blog.itpub.net/28916011/viewspace-2093197/ 最近,朋友去乐视面试了mysql DBA,以下是我据整理的乐视mysql面试题答案,供大家参考 ...

  7. Redirect

    Redirect To use this Class, add the following to the top of the file. use Redirect; Redirect::to($pa ...

  8. Debug 之 VS2010网站生成成功,但是发布失败

    用vs做好了网站.清理解决方案和重新生成解决方案都可以.但是发布不能成功.发布不能成功,有错误还好,郁闷的是竟然没有错误提示. 解决方法: 1.发布文件夹权限问题.重新找个地方建立一个发布文件夹即可. ...

  9. Asp.Net 5使用第三方容器

    这几天在学习Asp.Net 5,现在文档以及博客之类的资料实在太少了,不看源码几乎举步维艰,好在全都是开源的,看看微软的代码也获益良多. 看到DependencyInjection的代码里除了默认的容 ...

  10. SQL中N $ # @的作用

    declare @sql nvarchar(4000) set @sql= N'select @TotalRecords=count(*) from ' + N'(' + @sqlFullPopula ...