IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 为什么StringBuffer比String在拼接的时候效率高? -> 正文阅读

[移动开发]为什么StringBuffer比String在拼接的时候效率高?

1. 什么是StringBuffer

大家都知道StringBuffer是可变的字符串对象,那么为什么可变呢,为什么效率比不可变字符串String要高呢,下面我们从多个角度来分析这个原因。

2. 源码继承抽象类AbstractStringBuilder

abstract class AbstractStringBuilder implements Appendable, CharSequence {

    char[] value;

    int count;


    AbstractStringBuilder() {
    }


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

    @Override
    public int length() {
        return count;
    }

    public int capacity() {
        return value.length;
    }


    public void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > 0)
            ensureCapacityInternal(minimumCapacity);
    }

    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;
    }

2.1 append方法

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;
    }

2.2 toString方法

toString方法就是创建一个新的String对象,赋值当前内容。

    @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

2.3 ensureCapacityInternal扩容方法

通过源码我们可以看出,StringBuffer的底层结构和String一样都是char[]数组类型,不同的是StringBuffer有他的扩容机制,默认容量为16,当我们的内容大于我们的数组长度时,会将我们的容积扩大一倍还加2的大小。

点开我们的Arrays.copy方法

    public static char[] copyOf(char[] original, int newLength) {
        char[] copy = new char[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

我们会发现它的底层也是创建了一个新的数组对象,并赋值了扩大后的长度,再调用C语言的native方法拷贝了一份,返回新的数组给我们。

3. 都是创建对象,为什么比String的效率高呢?

有同学就会问了,假如不考虑扩容机制的前提下,String和StringBuffer的效率是否是一样的呢?要回答这个问题我们只能从字节码的角度来分析。将我们的代码生成CLASS文件,再反编译成汇编码。

编译前:

    public static void main(String[] args) {
        String a = "a";

        for (int i = 0; i< 10; i++){
            a += "b";
        }

        System.out.println("========================");


        StringBuilder c = new StringBuilder("c");

        for (int i = 0; i< 10; i++){
            c.append("d");
        }
    }  
    Code:
       0: ldc           #2                  // String a
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: bipush        10
       8: if_icmpge     37
      11: new           #3                  // class java/lang/StringBuilder
      14: dup
      15: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      18: aload_1
      19: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: ldc           #6                  // String b
      24: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      30: astore_1
      31: iinc          2, 1
      34: goto          5
      
      37: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      40: ldc           #9                  // String ========================
      42: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      
      45: new           #3                  // class java/lang/StringBuilder
      48: dup
      49: ldc           #11                 // String c
      51: invokespecial #12                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
      54: astore_2
      55: iconst_0
      56: istore_3
      57: iload_3
      58: bipush        10
      60: if_icmpge     76
      63: aload_2
      64: ldc           #13                 // String d
      66: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      69: pop
      70: iinc          3, 1
      73: goto          57
      76: return

通过汇编码,我们明显的看到,String它在拼接对象的时候是循环创建StringBuffer对象再new一个String对象,而StringBuffer则一直循环的是append方法,最后再返回一个new String对象,所以比String效率高。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:49:28  更:2021-12-01 17:49:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:59:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码