StringBuilder的容量capacity变化规则

2023-05-16

StringBuilder的容量capacity变化,是每次2倍增长吗?(jdk1.8)

测试代码 1

StringBuilder sb = new StringBuilder();
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("000");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());

运行结果 1

16----0
16----16
34----19
70----35
70----51

测试代码 2

StringBuilder sb = new StringBuilder();
sb.append("0000_0000_0000_0");
System.out.println(sb.capacity() + "----" + sb.length());
sb.append("0000_0000_0000_0000");
System.out.println(sb.capacity() + "----" + sb.length());

运行结果 2

16----16
35----35

问题

运行结果1运行结果2都能看出,StringBuilder的容量变化规律貌似不再是网上很多人所说的那样(容量默认为16,追加数据时,如果容量不够,则每次2倍整地扩容,直到容量不小于StringBuilder的长度值为止。)
那容量的变化规律到底是什么样的呢?接下来进入源码进行分析。

测试代码 1 的源码分析

public StringBuilder() {
    super(16);
}

// StringBuilder的父类AbstractStringBuilder
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * 该变量用于存储字符(可见StringBuilder底层用的是字符数组实现的)
     * The value is used for character storage.
     */
    char[] value;

    /**
     * 已使用的字符个数
     * The count is the number of characters used.
     */
    int count;

    // ...

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

    // ...
}
  • 先进入StringBuilder的构造方法,其又调用了父类的构造,初始化容量capacity依然还是16。这就是为何运行结果1中第一组数据中容量capacity为16的原因。
  • sb.append("0000_0000_0000_0");执行后因为长度还是16,没有超过当前容量(capacity = 16)的范围,所以运行结果还是不变。
  • sb.append("000");执行后,容量capacity突然变为34,竟然不是2*16=32,why?容量因为这句代码的执行发生了改变,那么容量的变化规则一定在append方法之中。进入append方法的源码发现:
    ensureCapacityInternal(count + len);这句代码就是重点,用于计算容量的大小的。
public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();

    //调用该方法,确定最终容量Capacity
    ensureCapacityInternal(count + len);

    str.getChars(0, len, value, count);
    count += len;
    return this;
}
  • 既然找到了方法,那就看看容量的具体变化规则吧:
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
}

其中minimumCapacity即为(count + len)的值,即 (已使用的字符个数 + 追加的新串的长度)的和(16 + 3 = 19),暂且叫最小容量值。

void expandCapacity(int minimumCapacity) {
    // 容量的变化规则在此
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

起初value.length为容量的默认值16,因newCapacity = value.length * 2 + 2;所以有newCapacity = 34即追加后的新容量为34。
容量的变化规律是2倍+2?
测试代码1看起来下面的测试代码也能证明貌似是这样的,但是测试代码2的运行结果如何解释呢?,看源码,下面还有一句:

if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;

这句代码的意思是,如果原容量的2倍再加2的结果还小于最小容量值minimumCapacity的话,新的容量将按照最小容量值minimumCapacity来计算。此刻一切都明白了。

总结

StringBuilder的容量Capacity变化规则为:

  1. 初始值为16;
  2. 如果minimumCapacity(新添加的数据长度和已有数据长度的和)小于当前容量Capacity,则添加数据后容量Capacity不变;
  3. 如果minimumCapacity(新添加的数据长度和已有数据长度的和)大于当前容量Capacity,但minimumCapacity**小于**当前容量Capacity的2倍加2,则添加数据后容量Capacity变为上次容量的2倍加2;
  4. 如果minimumCapacity(新添加的数据长度和已有数据长度的和)大于当前容量Capacity的2倍加2,则添加数据后容量Capacity即为minimumCapacity(新添加的数据长度和已有数据长度的和)。
初始值原容量 < 总内容 <= 2 * 原容量 + 2总内容 > 2 * 原容量 + 2
162 * 原容量 + 2内容总长度
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

StringBuilder的容量capacity变化规则 的相关文章

  • 机器人正解和逆解

    正解FK 给定机器人各关节的角度 xff0c 计算出机器人末端的空间位置 逆解IK 已知机器人末端的位置和姿态 xff0c 计算机器人各关节的角度值 挖个坑待完善
  • LeetCode—232 用栈实现队列 Cpp&Python

    LeetCode 225 用队列实现栈 Cpp amp Python 一 方法与思路二 C 43 43 代码三 Python代码 一 方法与思路 使用栈实现队列的下列操作 xff1a push x 将一个元素放入队列的尾部 pop 从队列首
  • E: Unable to locate package解决办法

    问题 xff1a E Unable to locate package 解决 xff1a sudo apt span class token operator span get updade
  • Yolo框架简介

    YOLO xff08 You Only Look Once xff09 是一种基于深度神经网络的对象识别和定位算法 xff0c 其最大的特点是运行速度很快 xff0c 可以用于实时系统 现在YOLO已经发展到v4版本 论文地址 xff1a
  • Ubuntu下编辑权限只读文件的方法

    首先要注意的是只读文件一般都是系统文件 xff0c 或者软件配置文件 xff0c 修改时要尤其谨慎 本文提供两种方法 xff1a 方法一 首先安装一个插件 span class token function sudo span apt sp
  • Ros下Aruco模块的使用

    生成ARUCO ROS MARKER 链接 http chev me arucogen 首先启动ros roscore 打开相机节点 xff0c 在此提供usb相机与Realsense D435i的启动方法 xff1a roslaunch
  • 脚气、灰指甲治疗实验方案

    脚气 xff08 已临床实验 xff09 脚气 xff0c 又叫足廯 香港脚 糜烂性脚气 症状 xff1a 80 都是这种类型 常见于多汗人群 角质层被汗水浸软 xff0c 发白了以后 xff0c 走动不断摩擦表皮脱落 xff0c 露出鲜红
  • VS2015显示“正在从以下位置加载符号“的解决办法

    解决方法 xff1a VS 工具 选项 调试 符号 看到 MicroSoft符号服务器 xff0c 去掉方框中的 xff0c 确定即可 xff0c 之后就不会再调试时加载
  • 【面包】STM32学习笔记(二) --- USART 串口通信学习总结

    tip xff1a 如有错误 xff0c 希望指出 xff0c 非常感谢 xff01 目录 简介一 USART是什么 xff1f 二 问答通信方式1 USART和UART区别2 单工 半双工 全双工区别 三 代码实验1 说明2 代码初始化配
  • [论文阅读笔记] Reciprocal n-body Collision Avoidance(ORCA/RVO2)

    论文阅读 Reciprocal n body Collision Avoidance ORCA RVO2 文章目录 论文阅读 Reciprocal n body Collision Avoidance ORCA RVO2 论文地址Intro
  • 在VSCode中搭建C++编译环境

    在VSCode中搭建C 43 43 编译环境 VSCode当中搭建C 43 43 环境下载VSCode下载MinGW配置文件撰写测试小程序 VSCode当中搭建C 43 43 环境 vscode作为一款轻量级编程软件深受编程人员喜爱 xff
  • 【C++学习笔记】头文件详解

    个人整理学习用 xff0c 非教材 xff0c 有错误欢迎指正 头文件 究竟什么是头文件 xff1f 首先说明一个概念 xff0c 所谓的文件后缀并不是必须的 xff0c 在Linux下这种特点尤为明显 对于编译器来说 xff0c 无论是
  • 编程实现字符串连接函数strcat()

    按如下函数原型编程实现字符串连接函数strcat 的功能 void MyStrcat char dstStr char srcStr 输入提示信息 xff1a Input a string Input another string 输入字符
  • UDP通讯

    目录 利用DatagramSocket发送和接收UDP数据报 DatagramPacket构造方法说明 利用DatagramPacket和Datagramsocket简单实现服务器和客户端的通信 UDP协议通讯的用户状态跟踪 利用Datag
  • ubuntu 下C/C++文件编写

    1 Ubuntu下c cpp文件 1 1 cmake方式编译 cmake通常建立CmakeLists txt xff0c 通过cmake命令生成makefile文件编译工程 文件内容 xff1a span class token numbe
  • C语言基础入门:链表详解篇

    链表概述 链表是一种常见的重要的数据结构 它是动态地进行存储分配的一种结构 它可以根据需要开辟内存单元 链表有一个 头指针 变量 xff0c 以head表示 xff0c 它存放一个地址 该地址指向一个元素 链表中每一个元素称为 结点 xff
  • Linux c udp广播

    文章目录 1 对比2 代码2 1 服务端2 2 客户端 1 对比 服务端 xff1a 需要利用这个函数开发套接字的发广播权限 xff0c 并且需要客户端地址绑定为广播地址 span class token function setsocke
  • React—— HelloWorld

    React 学习笔记 Hello WorldJSX JavaScript XML 语法规则JavaScript 语法函数组件 类组件 amp 属性 props组合组件 生命周期函数 xff08 不全 xff09 amp 状态 state事件
  • Linux下makefile 编译项目

    文章目录 1 规划makefile编写2 makefile文件2 1 根目录下common mk2 2 config mk2 3 根目录makefile 2 4 其他目录下 1 规划makefile编写 a 根目录下放三个文件 xff1a
  • RPLIDAR激光雷达测试

    本文主要介绍PRLIDAR A2M8 R2激光雷达的的测试过程 关于该激光雷达的具体参数和描述 xff0c 可以直接去官网查询 本文的测试环境为Ubantu16 04 ROS xff08 kinetic xff09 关于Ubantu16 0

随机推荐