#深度解析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);
    }
}
相关文章
|
存储 缓存 文件存储
如何保证分布式文件系统的数据一致性
分布式文件系统需要向上层应用提供透明的客户端缓存,从而缓解网络延时现象,更好地支持客户端性能水平扩展,同时也降低对文件服务器的访问压力。当考虑客户端缓存的时候,由于在客户端上引入了多个本地数据副本(Replica),就相应地需要提供客户端对数据访问的全局数据一致性。
33076 80
如何保证分布式文件系统的数据一致性
|
前端开发 容器
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局(上)
HTML5+CSS3前端入门教程---从0开始通过一个商城实例手把手教你学习PC端和移动端页面开发第8章FlexBox布局
17818 24
|
设计模式 存储 监控
设计模式(C++版)
看懂UML类图和时序图30分钟学会UML类图设计原则单一职责原则定义:单一职责原则,所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。bad case:IPhone类承担了协议管理(Dial、HangUp)、数据传送(Chat)。good case:里式替换原则定义:里氏代换原则(Liskov 
36801 22
设计模式(C++版)
|
存储 编译器 C语言
抽丝剥茧C语言(初阶 下)(下)
抽丝剥茧C语言(初阶 下)
|
机器学习/深度学习 人工智能 自然语言处理
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
带你简单了解Chatgpt背后的秘密:大语言模型所需要条件(数据算法算力)以及其当前阶段的缺点局限性
24873 15
|
机器学习/深度学习 弹性计算 监控
重生之---我测阿里云U1实例(通用算力型)
阿里云产品全线降价的一力作,2023年4月阿里云推出新款通用算力型ECS云服务器Universal实例,该款服务器的真实表现如何?让我先测为敬!
36786 15
重生之---我测阿里云U1实例(通用算力型)
|
SQL 存储 弹性计算
Redis性能高30%,阿里云倚天ECS性能摸底和迁移实践
Redis在倚天ECS环境下与同规格的基于 x86 的 ECS 实例相比,Redis 部署在基于 Yitian 710 的 ECS 上可获得高达 30% 的吞吐量优势。成本方面基于倚天710的G8y实例售价比G7实例低23%,总性价比提高50%;按照相同算法,相对G8a,性价比为1.4倍左右。
|
存储 算法 Java
【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的限流器RateLimiter功能服务
随着互联网的快速发展,越来越多的应用程序需要处理大量的请求。如果没有限制,这些请求可能会导致应用程序崩溃或变得不可用。因此,限流器是一种非常重要的技术,可以帮助应用程序控制请求的数量和速率,以保持稳定和可靠的运行。
29925 52

热门文章

最新文章