JDK源码学习系列02----AbstractStringBuilder
JDK源码学习系列02----AbstractStringBuilder
因为看StringBuffer 和 StringBuilder 的源码时发现两者都继承了AbstractStringBuilder,并且很多方法都是直接super的父类AbstractStringBuilder的方法,所以还是决定先看AbstractStringBuilder的源码,然后再看StringBuffer 和 StringBuilder.
1.成员变量
AbstractStringBuilder和String一样,在其内部都是以字符数组的形式实现的。也就是String,StringBuffer以及StringBuilder在其内部都是以字符数组的形式实现的。
char value[];
int count;
2.构造函数
AbstractStringBuilder的构造函数中传入的capacity是指容量,实际长度是以leng中的count表示的,注意区分容量和实际长度。
AbstractStringBuilder() {
} AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
3.容量和长度
public int length() {
return count;
}
public int capacity() {
return value.length;
}
4.AbstractStringBuilder的扩容
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {//如果传入的容量大于原来的容量就扩容
expandCapacity(minimumCapacity);
}
} void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;//首先默认扩容为 (原容量+1)*2
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {//如果传入的容量大于 默认扩容量,则传入容量为新容量
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
5.字符串减少存储空间
如果实际长度小于容量,为了减少存储空间,就把容量缩小为刚好满足字符串长度。
public void trimToSize() {
if (count < value.length) {
value = Arrays.copyOf(value, count);
}
}
6.void setLength(int newLength)
public void setLength(int newLength) {
if (newLength < 0)
throw new StringIndexOutOfBoundsException(newLength);
if (newLength > value.length)//设置长度大于容量时先扩容
expandCapacity(newLength); if (count < newLength) {//设置长度大于原来长度时,后面部分补以空白
for (; count < newLength; count++)
value[count] = '\0';
} else {
count = newLength;
}
}
7.char charAt(int index)
public char charAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
return value[index];
}
8.void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)
一定要注意参数情况的考虑,自己编程时一定要养成好习惯。主要是调用了System.arraycopy()的方法,以后具体分析。
public void getChars(int srcBegin, int srcEnd, char dst[],
int dstBegin)
{
if (srcBegin < 0)
throw new StringIndexOutOfBoundsException(srcBegin);
if ((srcEnd < 0) || (srcEnd > count))
throw new StringIndexOutOfBoundsException(srcEnd);
if (srcBegin > srcEnd)
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
9.void setCharAt(int index, char ch)
方法的源码很简单,是直接替换该index的值,而不是后移之类的,因为是数组,不可变长度。
public void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
value[index] = ch;
}
10.append(String str)
对于StringBuffer和StringBuilder重要的append()方法的源码闪亮登场咯~~
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";//若传入为null,则会在后面加上“null”
int len = str.length();
if (len == 0) return this;//传入长度为0,则返回本身
int newCount = count + len;
if (newCount > value.length)//传入后的长度大于容量就扩容
expandCapacity(newCount);
str.getChars(0, len, value, count);//用的是getChars()为value传值
count = newCount;
return this;
}
11.append(CharSequence s, int start, int end)
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))//一定要注意情况考虑
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start;
if (len == 0)
return this;
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
for (int i=start; i<end; i++)//用的是charAt()为value循环赋值
value[count++] = s.charAt(i);//!!
count = newCount;
return this;
}
12.append(char str[])
若是字符数组,用的是System.arraycopy()方法。
public AbstractStringBuilder append(char str[]) {
int newCount = count + str.length;
if (newCount > value.length)
expandCapacity(newCount);
System.arraycopy(str, 0, value, count, str.length);
count = newCount;
return this;
}
13.append(boolean b)
这个源码很简单
public AbstractStringBuilder append(boolean b) {
if (b) {
int newCount = count + 4;
if (newCount > value.length)
expandCapacity(newCount);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else {
int newCount = count + 5;
if (newCount > value.length)
expandCapacity(newCount);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}
14.append(int i)
public AbstractStringBuilder append(int i) {
if (i == Integer.MIN_VALUE) {
append("-2147483648");
return this;
}
int appendedLength = (i < 0) ? stringSizeOfInt(-i) + 1 : stringSizeOfInt(i);//!!!
int spaceNeeded = count + appendedLength;
if (spaceNeeded > value.length)
expandCapacity(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;
}
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE }; // Requires positive x
static int stringSizeOfInt(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
15.delete(int start, int end)
主要还是用的System.arraycopy()
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;
}
return this;
}
16.reverse()
这个是StringBuffer和StringBuilder常用到的方法,而String并没有这个牛逼的功能~~
public AbstractStringBuilder reverse() {
boolean hasSurrogate = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; --j) {
char temp = value[j];
char temp2 = value[n - j];
if (!hasSurrogate) {
hasSurrogate = (temp >= Character.MIN_SURROGATE && temp <= Character.MAX_SURROGATE)
|| (temp2 >= Character.MIN_SURROGATE && temp2 <= Character.MAX_SURROGATE);
}
value[j] = temp2;
value[n - j] = temp;
}
if (hasSurrogate) {
// Reverse back all valid surrogate pairs
for (int i = 0; i < count - 1; i++) {
char c2 = value[i];
if (Character.isLowSurrogate(c2)) {
char c1 = value[i + 1];
if (Character.isHighSurrogate(c1)) {
value[i++] = c1;
value[i] = c2;
}
}
}
}
return this;
}
17. String toString()
这个只是一个抽象的方法,没有方法体。
public abstract String toString();
JDK源码学习系列02----AbstractStringBuilder的更多相关文章
- JDK源码学习系列03----StringBuffer+StringBuilder
JDK源码学习系列03----StringBuffer+StringBuilder 由于前面学习了StringBuffer和StringBuilder的父类A ...
- JDK源码学习系列05----LinkedList
JDK源码学习系列05----LinkedList 1.LinkedList简介 LinkedList是基于双向链表实 ...
- JDK源码学习系列04----ArrayList
JDK源码学习系列04----ArrayList 1. ...
- JDK源码学习系列01----String
JDK源码学习系列01----String 写在最前面: 这是我JDK源码学习系列的第一篇博文,我知道 ...
- JDK源码学习笔记——Integer
一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...
- Spring5.0源码学习系列之浅谈BeanFactory创建
Spring5.0源码学习系列之浅谈BeanFactory创建过程 系列文章目录 提示:Spring源码学习专栏链接 @ 目录 系列文章目录 博客前言介绍 一.获取BeanFactory主流程 二.r ...
- Java并发包源码学习系列:CLH同步队列及同步资源获取与释放
目录 本篇学习目标 CLH队列的结构 资源获取 入队Node addWaiter(Node mode) 不断尝试Node enq(final Node node) boolean acquireQue ...
- Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类
目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...
- Java并发包源码学习系列:阻塞队列实现之PriorityBlockingQueue源码解析
目录 PriorityBlockingQueue概述 类图结构及重要字段 什么是二叉堆 堆的基本操作 向上调整void up(int u) 向下调整void down(int u) 构造器 扩容方法t ...
随机推荐
- WebBrowser控件禁用超链接转向、脚本错误提示、默认右键菜单和快捷键
原文:WebBrowser控件禁用超链接转向.脚本错误提示.默认右键菜单和快捷键 WebBrowser控件禁用超链接转向.脚本错误提示.默认右键菜单和快捷键从 VS2005开始,VS自带的 WebBr ...
- POJ 3040 Allowance 贪心
这题目的贪心思路还是有一点细节问题的. 还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的. 思路如下: 假设要给奶牛的钱为C 1)从大面值到小面值一次拿钱,能拿多少拿多少 ...
- IOS开发之----四舍五入问题
方法一: -(NSString *)notRounding:(float)price afterPoint:(int)position{ NSDecimalNumberHandler* roundin ...
- Linux 技巧之 Grub 超实用技巧
1. 简单介绍 什么是 GRUB?GRUB 全名Grand Unified Boot Loader,它是一个引导装入器 -- 它负责装入内核并引导 Linux 系统.GRUB 还能够引导其他操作系统, ...
- POJ3313 【随便写了个spfa就一A了,嗨皮】
我顺便明白了....英文题意理解其实好大一部分还是靠感觉,然后自己猜题意,试题意. 你要是纠结于英文你就跪了. #include <iostream> #include <cstdi ...
- Android Studio Gradle 添加.so 支持文件
近期发展Android Wear 关注商品.官员Demo所有gradle 工程. 当然,我也用eclipse配置一个可行的环境. 问题来了,eclipse,android studio 开发 andr ...
- 使用Ajax以及Jquery.form异步上传图片
一.前言 之前做图片上传一直用的第三方插件,Uploadify 这个应该是用的比較多的,相同也用过别的,在方便了自己的同一时候也非常赞叹人家的功能. 思来想去,仅仅会用别的人东西,始终自己学到的少, ...
- ios 上拉载入下拉刷新Dome
为练手写了一个小的上拉载入很多其它下拉刷新的小的Dome . 没有太多的技术含量,仅仅是作为新手的启示用.是上一篇下拉载入的扩展.先看一下那个再看这个就easy非常多. Dome下载:http://d ...
- python实现人人网用户数据爬取及简单分析
这是之前做的一个小项目.这几天刚好整理了一些相关资料,顺便就在这里做一个梳理啦~ 简单来说这个项目实现了,登录人人网并爬取用户数据.并对用户数据进行分析挖掘,终于效果例如以下:1.存储人人网用户数据( ...
- Web Api 2(Cors)Ajax跨域访问
支持Ajax跨域访问ASP.NET Web Api 2(Cors)的简单示例教程演示 随着深入使用ASP.NET Web Api,我们可能会在项目中考虑将前端的业务分得更细.比如前端项目使用Ang ...