JDK源码阅读(3):AbstractStringBuilder、StringBuffer、StringBuilder类阅读笔记
AbstractStringBuilder
abstract class AbstractStringBuilder implements Appendable, CharSequence{
...
}
1. inflate方法
inflate()
方法可以将当前的Latin1编码的字符串膨胀到16位,即UTF16编码(Latin1编码为8位)
/**
* If the coder is "isLatin1", this inflates the internal 8-bit storage
* to 16-bit <hi=0, low> pair storage.
*/
private void inflate() {
if (!isLatin1()) {
return;
}
byte[] buf = StringUTF16.newBytesFor(value.length);
StringLatin1.inflate(value, 0, buf, 0, count);
this.value = buf;
this.coder = UTF16;
}
2. ensureCapacity方法
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0) {
ensureCapacityInternal(minimumCapacity);
}
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
if (minimumCapacity - oldCapacity > 0) {
// 拷贝过去
value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder);
}
}
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = value.length >> coder;
int newCapacity = (oldCapacity << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
ensureCapacity(miniCapacity)
方法保证当前容器的大小不小于miniCapacity
,如果小于的话就要进行扩容处理。扩容成下面两者中的较大值。
- miniCapacity
- 2*oldCapacity
3. setCharAt方法
setCharAt()
方法可以将index处的字符设为ch
public void setCharAt(int index, char ch) {
checkIndex(index, count);
if (isLatin1() && StringLatin1.canEncode(ch)) {
value[index] = (byte)ch;
} else {
if (isLatin1()) {
inflate();
}
StringUTF16.putCharSB(value, index, ch);
}
}
4. append方法
append()
方法根据参数类型不同,在字符串后面追加。
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());
}
值得一提的是这个appendNull()
方法,当我们在试图append一个空对象时,它居然选择在builder串后面加上一个“null”,看下面的示例。
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("a");
String s = null;
stringBuilder.append(s);
System.out.println(stringBuilder.toString());
System.out.println(stringBuilder.toString().length());
}
输出结果居然是
anull
5
也就是说,当append空对象时,会append一个“null”字符串。
另外,当我们尝试append一个boolean对象时,会append一个“true”串或者“false”串。
5. delete方法
delete
方法删除builder中的一段
public AbstractStringBuilder delete(int start, int end) {
int count = this.count;
if (end > count) {
end = count;
}
checkRangeSIOOBE(start, end, count);
int len = end - start;
if (len > 0) {
shift(end, -len);
this.count = count - len;
}
return this;
}
类似地还有deleteCharAt
public AbstractStringBuilder deleteCharAt(int index) {
checkIndex(index, count);
shift(index + 1, -1);
count--;
return this;
}
6. reverse方法
reverse()
方法可以逆转字符的顺序。
public AbstractStringBuilder reverse() {
byte[] val = this.value;
int count = this.count;
int coder = this.coder;
int n = count - 1;
if (COMPACT_STRINGS && coder == LATIN1) {
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
byte cj = val[j];
val[j] = val[k];
val[k] = cj;
}
} else {
StringUTF16.reverse(val, count);
}
return this;
}
实际的方法就是双指针靠拢+交换、
StringBuffer
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{
StringBuffer
类几乎所有方法都是通过super
关键字调用AbstractStringBuilder
父类的方法。
StringBuffer
实现同步的方式就是给所有方法加上synchronized
关键字。
1. toStringCache变量
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
*/
private transient String toStringCache;
toStringCache
缓存了toString()
方法的最后一次调用的值,在每次StringBuffer被修改前这个缓存会清除。
toString()
方法中检查如果有缓存,就直接返回缓存。这样不用每次都处理toString()
的过程,而只在需要的时候处理。
public synchronized String toString() {
if (toStringCache == null) {
return toStringCache =
isLatin1() ? StringLatin1.newString(value, 0, count)
: StringUTF16.newString(value, 0, count);
}
return new String(toStringCache);
}
StringBuilder
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
...
}
StringBuilder
类几乎所有方法都是通过super
关键字调用AbstractStringBuilder
父类的方法。
JDK源码阅读(3):AbstractStringBuilder、StringBuffer、StringBuilder类阅读笔记的更多相关文章
- Java1.8 JDK源码中,对两个类进行 按位与 操作是什么意思
Java容器类库中的Map接口(java\util\Map.java)中有一个Entry接口(java\util\Map.java),其中有几个接口方法用到了类和类的按位与操作,即类和类之间有 &am ...
- JDK源码阅读顺序
很多java开发的小伙伴都会阅读jdk源码,然而确不知道应该从哪读起.以下为小编整理的通常所需阅读的源码范围. 标题为包名,后面序号为优先级1-4,优先级递减 1.java.lang 1) Obj ...
- JDK源码学习系列03----StringBuffer+StringBuilder
JDK源码学习系列03----StringBuffer+StringBuilder 由于前面学习了StringBuffer和StringBuilder的父类A ...
- 如何阅读JDK源码
JDK源码阅读笔记: https://github.com/kangjianwei/LearningJDK 如何阅读源码,是每个程序员需要面临的一项挑战. 为什么需要阅读源码?从实用性的角度来看,主要 ...
- 如何有效的阅读JDK源码
阅读Java源码的前提条件: 1.技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持. 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃<Core Java>,那样 ...
- 利用IDEA搭建JDK源码阅读环境
利用IDEA搭建JDK源码阅读环境 首先新建一个java基础项目 基础目录 source 源码 test 测试源码和入口 准备JDK源码 下图框起来的路径就是jdk的储存位置 打开jdk目录,找到sr ...
- jdk源码阅读笔记-HashSet
通过阅读源码发现,HashSet底层的实现源码其实就是调用HashMap的方法实现的,所以如果你阅读过HashMap或对HashMap比较熟悉的话,那么阅读HashSet就很轻松,也很容易理解了.我之 ...
- 如何阅读jdk源码?
简介 这篇文章主要讲述jdk本身的源码该如何阅读,关于各种框架的源码阅读我们后面再一起探讨. 笔者认为阅读源码主要包括下面几个步骤. 设定目标 凡事皆有目的,阅读源码也是一样. 从大的方面来说,我们阅 ...
- JDK源码阅读(三):ArraryList源码解析
今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...
- JDK源码阅读(一):Object源码分析
最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...
随机推荐
- Javascript - 异步操作和读取文件
node.js读取文件 node.js内置了异步读取文件的模块,可以很方便地读取文件的数据.先创建三个txt文档,在根目录下创建一个readFile.js 输入以下代码,然后在vscode的终端中输入 ...
- 超详细教程2021新版oracle官网下载Windows JAVA-jdk11并安装配置(其他版本流程相同)
异想之旅:本人博客完全手敲,绝对非搬运,全网不可能有重复:本人无团队,仅为技术爱好者进行分享,所有内容不牵扯广告.本人所有文章发布平台为CSDN.博客园.简书和开源中国,后期可能会有个人博客,除此之外 ...
- spring-data-redis 连接泄漏,我 TM 人傻了
本系列是 我TM人傻了 系列第四期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...
- 三大操作系统对比使用之·Windows10
时间:2018-10-29 记录:byzqy 本篇是一篇个人对Windows系统使用习惯.技巧和应用推荐的文档,在此记录.分享和后续查询备忘. 打开终端: Win+R,调出"运行" ...
- 分享几个下载豆瓣资源的chrome插件
最近chrome终于以4.69%的市场占有率击败firefox成为中国第二大浏览器.(第一当然是争霸宇宙的IE了) 虽然chrome官方应用程序商店有不少豆瓣的辅助插件,但大多没什么用.属于蛋疼插件. ...
- 在CentOs7源码安装mysql-5.6.35单实例数据库
首先安装依赖包,避免在安装过程中出现问题 [root@bogon liuzhen]# yum -y install gcc gcc-c++[root@bogon liuzhen]# yum -y in ...
- C#多线程开发-线程同步 02
上一篇文章主要带领大家认识了线程,也了解到了线程的基本用法和状态,接下来就让我们一起学习下什么是线程同步. 线程中异常的处理 在线程中始终使用try/catch代码块是非常重要的,因为不可能在线程代码 ...
- Hystrix集群及监控turbine
Hystrix集群及监控turbine 前面Dashboard演示的仅仅是单机服务监控,实际项目基本都是集群,所以这里集群监控用的是turbine. turbine是基于Dashboard的. 先搞个 ...
- python实现分水岭算法分割遥感图像
1. 定义 分水岭算法(watershed algorithm)可以将图像中的边缘转化为"山脉",将均匀区域转化为"山谷",在这方面有助于分割目标. 分水岭算法 ...
- 循环神经网络LSTM RNN回归:sin曲线预测
摘要:本篇文章将分享循环神经网络LSTM RNN如何实现回归预测. 本文分享自华为云社区<[Python人工智能] 十四.循环神经网络LSTM RNN回归案例之sin曲线预测 丨[百变AI秀]& ...