博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从源码分析:分析Java中的StringBuilder
阅读量:4039 次
发布时间:2019-05-24

本文共 4643 字,大约阅读时间需要 15 分钟。

我们知道,在java中,如果要对于一个字符串进行操作,比如增删操作,如果直接用+来进行的话,效率是比较低的。作为替代,我们一般使用StringBuilder来进行这样的操作。

所以,这一次,我们就来研究一下StringBuilder的源码

构造函数

public final class StringBuilder    extends AbstractStringBuilder    implements java.io.Serializable, CharSequence{
/** use serialVersionUID for interoperability */ static final long serialVersionUID = 4383685877147921099L; /** * Constructs a string builder with no characters in it and an * initial capacity of 16 characters. */ public StringBuilder() {
super(16); } /** * Constructs a string builder with no characters in it and an * initial capacity specified by the {@code capacity} argument. * * @param capacity the initial capacity. * @throws NegativeArraySizeException if the {@code capacity} * argument is less than {@code 0}. */ public StringBuilder(int capacity) {
super(capacity); } /** * Constructs a string builder initialized to the contents of the * specified string. The initial capacity of the string builder is * {@code 16} plus the length of the string argument. * * @param str the initial contents of the buffer. */ public StringBuilder(String str) {
super(str.length() + 16); append(str); } /** * Constructs a string builder that contains the same characters * as the specified {@code CharSequence}. The initial capacity of * the string builder is {@code 16} plus the length of the * {@code CharSequence} argument. * * @param seq the sequence to copy. */ public StringBuilder(CharSequence seq) {
this(seq.length() + 16); append(seq); } ...}

可以看到,当我们不指定初始的容量的时候,会调用父类AbstractStringBuilder的构造函数,并默认初始容量为16。

所以,我们来看看’AbstractStringBuilder’的构造方法:

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;    /**     * This no-arg constructor is necessary for serialization of subclasses.     */    AbstractStringBuilder() {    }    /**     * Creates an AbstractStringBuilder of the specified capacity.     */    AbstractStringBuilder(int capacity) {        value = new char[capacity];    }    ...}

其中,主要关注:

AbstractStringBuilder(int capacity) {
value = new char[capacity]; }

可以看到,在这里根据设定的初始容量,初始化出了一个相应长度的char型数组value

append方法

这里以str的append方法为例,看一下StringBuilder的append方法是怎样工作的。

首先是StringBuilder中的append(String str)方法。

public StringBuilder append(String str) {
super.append(str); return this;}

指向了父类中的append方法,那么就来看看父类中的定义:

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是为了保证容量能够装得下这个输入的str。

private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value, newCapacity(minimumCapacity)); }}private int newCapacity(int minCapacity) {
// overflow-conscious code 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;}

这里的扩容方式为先将容量乘2再加2,再与所需容量进行比较,若小于所需容量,则取所需容量,后面还有防止溢出的操作,写得非常严谨,这里值得我们学习与借鉴。获得更新后的容量后,新建一个新的容量的数组,并将之前的数据用Arrays.copyOf()方法复制进去,并更新为新的成员变量value

我们回到append方法中来,在进行完ensureCapacityInternal后,就要将所需添加的数据加进来了,这里调用的是StringgetChars方法。

# String.javapublic 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); } System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);}

这里调用System.arraycopy来将String内部的成员变量char型数组value(注意这里是String的,也就是append的参数里的那个变量)从0到str.length(),也就是所有成员,复制到dst中,也就是StringBuilder的成员变量value中。之后,便完成了整个append的操作。

转载地址:http://fmsdi.baihongyu.com/

你可能感兴趣的文章
[LeetCode By Python]125. Valid Palindrome
查看>>
[LeetCode By Python]136. Single Number
查看>>
[LeetCode By MYSQL] Combine Two Tables
查看>>
[Leetcode BY python ]190. Reverse Bits
查看>>
Android下调用收发短信邮件等(转载)
查看>>
Android中电池信息(Battery information)的取得
查看>>
SVN客户端命令详解
查看>>
Android/Linux 内存监视
查看>>
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
Phone双模修改涉及文件列表
查看>>
android UI小知识点
查看>>
Android之TelephonyManager类的方法详解
查看>>
android raw读取超过1M文件的方法
查看>>
ubuntu下SVN服务器安装配置
查看>>
MPMoviePlayerViewController和MPMoviePlayerController的使用
查看>>
CocoaPods实践之制作篇
查看>>
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>