#深度解析StringBuffer

基本介绍

StringBuffer代表可变的字符序列,可对字符串内容进行增删,很多方法与String相同,但是StringBuffer是可变长度的

StringBuffer是一个容器

StringBuffer类图如下

从类图中可以看出

StringBuffer的直接父类 是 AbstractStringBuilder

StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化

在父类中 AbstractStringBuilder 有属性 char[] value,不是 final

该 value 数组存放 字符串内容,存放在堆中

StringBuffer 是一个 final 类,不能被继承

因为 StringBuffer 字符内容是存在 char[] value, 所以在变化(增加/删除) 时,不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String

String 和 StringBuffer 相互转换

首先看一下StringBuffer的构造器

package com.wxit.stringbuffer;

/**
 * @Author wj
 * StringBuffer学习,构造器的使用
 **/
public class StringBuffer01 {
    public static void main(String[] args) {
        //创建一个大小为16的char[],用于存放字符内容
        StringBuffer stringBuffer01 = new StringBuffer();
        
        //2.通过构造器指定char[]的大小
        StringBuffer stringBuffer02 = new StringBuffer(100);

        //通过给一个String 创建 StringBuffer,char[] 大小就是str.length + 16
        StringBuffer stringBuffer03 = new StringBuffer("hello");
    }
}

以上三个构造器对应的源码如下图

代码示例如下

package com.wxit.stringbuffer;

/**
 * @Author wj
 * String与StringBuffer相互转化
 **/
public class StringAndStringBuffer {
    public static void main(String[] args) {

        //String --> StringBuffer
        String str = "hello world";
        //方式一 使用构造器
        StringBuffer stringBuffer = new StringBuffer(str);
        System.out.println(stringBuffer);

        StringBuffer stringBuffer1 = new StringBuffer();
        StringBuffer append = stringBuffer1.append(str);
        System.out.println(append);

        //StringBuffer -->  String
        StringBuffer stringBuffer2 = new StringBuffer("即使再小的帆也能远航");
        //方式一 : StringBuffer提供的toString方法
        String s = stringBuffer2.toString();
        System.out.println(s);

        //方式二:使用构造器
        String s1 = new String(stringBuffer2);
        System.out.println(s1);
    }
}

StringBuffer方法

从类图中可以看出StringBuffer中有众多方法

以上只是部分方法,还不包括父类的方法

下面列举常用的方法

常用方法

代码示例

package com.wxit.stringbuffer;

/**
 * @Author wj
 * StringBufferMethod常用方法
 **/
public class StringBufferMethod {
    public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer("你好");
        //增加
        buffer.append(",");
        buffer.append("吴杰");
        buffer.append("李婷").append("佳伟").append("子龙").append("子云").append("还有合一小家");
        System.out.println(buffer);

        //删
        System.out.println(buffer.delete(5,7));

        //改
        System.out.println(buffer.replace(4,6,"小昊"));

        //查找指定的子串在字符串第一次出现的索引,如果找不到返回-1
        System.out.println(buffer.indexOf("子云"));

        //插入  在索引为 0 的位置插入 "hello",原来索引为 9 的内容自动后移
        System.out.println(buffer.insert(0,"hello"));
    }
}

运行效果

StringBuffer练习

以下代码输出什么?为什么?

代码如下

package com.wxit.interview;

/**
 * @Author wj
 **/
public class Demo08 {
    public static void main(String[] args) {
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        System.out.println(sb.length());//4
    }
}

解析如下

首先 String str = null; 是成立的

然后进入到StringBuffer的源码中,查看append()方法,源码如下

@Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

从源码中看出StringBuffer中的append方法有调用了父类的append方法,所以,追进父类AbstractStringBuilder查看父类的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;
    }

又str为空,所以又调用了appendNull()方法,追进appendNull()方法,代码如下

  private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
    }

由此可以看出把空对象转化为字符数组'null'

故最后输出的结果应该为4

练习二

代码如下

package com.wxit.test;

import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.util.Scanner;

/**
 * @Author wj
 * 练习
 * 需求:输入价格,要求,价格的小数点前面每三位就用一个逗号隔开
 **/
public class StringBufferDemo01 {
    public static void main(String[] args) {
        /*
        思路分析
        1.定义一个Scanner 对象,接收用户的价格(String)
        2.希望使用到StringBuffer中的insert方法,需要将String 转换成StringBuffer
        3.然后使用相关的方法进行字符串的处理
         */

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入价格");
        String price = scanner.next();
        System.out.println("输入的价格为:" + price);
        StringBuffer sb = new StringBuffer(price); //123456.789
        //先完成一个最简单的实现
//        System.out.println(sb.lastIndexOf("."));
        System.out.println(sb.insert(sb.lastIndexOf(".") - 3,","));
        //有上面可得出规律为,先找到小数点的索引位置,然后向该索引的前三个位置插入一个逗号,所以要做一个循环
        for (int i = sb.lastIndexOf(".") - 3;i > 0; i -= 3){
            sb.insert(i,",");
        }
        System.out.println(sb);
    }
}
上一篇:克鲁斯卡尔算法


下一篇:女程序员的逆袭之路, 三面通过 15K,HR 说你只值 10K,为什么spring能最好地改变Android