StringBuilder和StringBuffer详解

1.1 基本概念

  • String描述的字符串是个常量,不可改变,会单独申请一块内存空间。在java代码中描述大量类似的字符串时,可能会造成内存空间的浪费
  • 为了解决上述问题,使用可改变的字符串即可:
    • Stringbuffer类 :JDK1.0开始存在,属于线程安全,所以效率低下
    • StringBuilder类 :JDK1.5开始存在,属于非线程安全,所以效率较高
    • 一般开发用StringBuilder

简单举例解释一下 ,线程安全和 非线程安全:

大妈买菜为例!一大堆大妈早上,就围在超市门口等开门,抢折扣的鸡蛋之类的食物。

  • 线程安全

    ​ 大妈们,必须按照超市规定,排队,一个一个买。等结算完金额之后,下一个大妈才能开始购物。要20分钟,才能卖完

    • 对于大妈来说:安全的
    • 对于超市来说:卖东西的效率是低下的
  • 非线程安全

    ​ 大妈们为了抢菜,又挤,又抢,还有人骂了起来,三下五除二,不到2分钟,菜就卖完了。

    • 对于大妈来说:不安全的,可能会发生意外
    • 对于超市来说:东西卖的贼快,效率高

1.2 StringBuilder常用的构造方法

方法声明 功能介绍
StringBuilder() 无参构造来构建对象,初始容量为16
StringBuilder( int capacity ) 根据参数指定的容量,来构造对象
StringBuilder( String str ) 根据字符串,来指定构造对象,容量大小为:16 + 字符串长度

1.3 StringBuilder常用成员方法

方法声明 功能介绍
int capacity() 返回方法调用对象的容量大小(虚拟大小)
int length() 返回字符串中的字符个数(实际大小)
StringBuilder insert( int offset, String str) 指定索引插入字符,返回引用(调用该方法)
StringBuilder append( String str ) 在字符串末尾追加字符串,返回引用
StringBuilder deleteCharAt( int index ) 删除指定索引的字符,返回引用
StringBuilder delete( int start, int end ) 从 start索引 开始删除字符,到 end索引-1 处,停止删除
StringBuilder replace( int start, int end, String str ) 从 start索引 开始,到end索引-1 处的字符串,全部用 str替换掉
StringBuilder reverse() 字符串翻转

1.4 StringBuilder的扩容算法的源码解析

举例探讨 StringBuilder的自动扩容机制:

StringBuilder sb = new StringBuilder("01234567");
String str = "qwertyuiop"
sb.append(str);  
  1. 看append方法的源码:

    @Override
        public StringBuilder append(String str) {
            // super,调用了父类的append方法
            super.append(str);
            // 返回this,即返回当前调用该方法的对象
            return this;
        }
    
  2. (append源码内) 进入父类的append方法,查看源码

public AbstractStringBuilder append(String str) {
    // 判断str是否为空
    if (str == null)
        return appendNull();
    
    // 获取当前str的长度
    int len = str.length();
    // ensureCapacityInternal方法,确保容量足够的方法
    // 参数count:即sb引用对象的长度,count= sb.length()
    ensureCapacityInternal(count + len);
    
    
/* ______________  进入ensureCapacityInternal方法 ____________*/

    // minimumCapacity = 扩容前的长度 + 追加字符串的长度
    private void ensureCapacityInternal(int minimumCapacity) {
        
        // char[] value (Stringbuilder本质上就是一个字符数组)
        // value.length:指Stringbuilder扩容前的容量
        // 这个if判断,是用来判断是否扩容,true,则扩容
        if (minimumCapacity - value.length > 0) {
            // Arrays.copyOf: 数组的拷贝,将数组的内容拷贝到一个新的数组中
            // 将 value,即扩容前的数组拷贝到, newCapacity(minimumCapacity)返回的数组中
            // newCapacity(minimumCapacity)返回的是一个,扩容前的容量*2+2的一个容量大小的数组
            value = Arrays.copyOf(
                value,
                newCapacity(minimumCapacity));
        }
    } 

总结:

  • StringBuilder的自动扩容机制为,扩容前的容量 * 2+ 2 = 扩容后的数组容量
  • 要特别注意,容量 != 长度, 容量 = 数组能够拥有的最大长度

StringBuilder和StringBuffer详解_第1张图片

  • 还有就是,如果一次性追加字符串的长度,超过了自动扩容后的容量。那么,会直接让追加后字符串的容量最为扩容后数组的容量

    StringBuilder和StringBuffer详解_第2张图片

  • StringBuilder、StringBuffer作为参数时,会改变本身的值。而String就不会

1.5 常见笔试考点

考点1:StringBuilder类的对象本身会被修改,为什么成员方法还要返回自身对象呢?

为了连续调用,即链式编程

sb.reverse().append("1").insert(0, "X").delete(0, 3);

考点2:实现 StringBuilder 和 String 之间的相互转换

  1. StringBuilder 转 String

    String str = sb.toString();
    
  2. String 转 StringBuilder

    // 构造方法即可
    StringBuilder s =new StringBuilder(str);
    

考点3:String,StringBuilder,StringBuffer三者之间效率比较

效率:StringBuilder > StringBuffer > String

你可能感兴趣的:(Java从0开始自学,java,字符串)