为什么StringBuffer比String在拼接的时候效率高?

2023-11-05 18:30

本文主要是介绍为什么StringBuffer比String在拼接的时候效率高?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简单了解String与StringBuffer

什么是StringBuffer?

可变的字符串对象,底层是一个char数组,但是该char数组是可变的,并且可以自动扩容。

字符串缓冲区

StringBuffer和StringBuider,StringBuffer和StringBuider的默认容是“16”。

StringBuffer与String的区别

String:不可变的字符序列,存储在字符串常量池中。

StringBuffer:可变的字符串对象。

StringBuffer可变的原理

创建StringBuffer的时候,预先在内存中申请一块空间,存储字符序列,如果预留空间不够用,则自动扩容存储更多的字符序列。


源码解析

源码继承抽象类AbstractStringBuilder 
public final class StringBufferextends AbstractStringBuilderimplements Serializable, CharSequence{  代码……  }

(这里删除了源码,只保留了类头)

 ensureCapacityInternal()  --- 扩容
private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0) {value = Arrays.copyOf(value,newCapacity(minimumCapacity));}}

StringBuffer的底层结构和String一样都是char[]数组类型,不同的是StringBuffer有他的扩容机制,默认容量为16,当我们的内容大于我们的数组长度时,会将我们的容积扩大。这里调用了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;}

Arrays.copy()的底层也是创建了一个新的数组对象,并赋值了扩大后的长度,返回新的数组给我们。

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

append方法就是添加字符,返回新的截取内容,当长度不够时进行扩容。

toString()

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

@Overridepublic String toString() {// Create a copy, don't share the arrayreturn new String(value, 0, count);}

为什么效率高?

都是创建对象,为什么StringBuffer效率要比String效率高?

不考虑扩容机制的前提下,String和StringBuffer的效率是否是一样的呢?

对于这个问题,我们从字节码的角度来分析。将我们的代码生成CLASS文件,再反编译成汇编码(这里我不会反编译)

    Code:0: ldc           #2                  // String a2: astore_13: iconst_04: istore_25: iload_26: bipush        108: if_icmpge     3711: new           #3                  // class java/lang/StringBuilder14: dup15: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V18: aload_119: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;22: ldc           #6                  // String b24: 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_131: iinc          2, 134: goto          537: 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;)V45: new           #3                  // class java/lang/StringBuilder48: dup49: ldc           #11                 // String c51: invokespecial #12                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V54: astore_255: iconst_056: istore_357: iload_358: bipush        1060: if_icmpge     7663: aload_264: ldc           #13                 // String d66: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;69: pop70: iinc          3, 173: goto          5776: return

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

    public static void getStr(){String str = "aaa";System.out.println(str);str = str + "bb";System.out.println(str);}

如果运行这段代码会发现先输出“aaa”,然后又输出“aaabb”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“aaa”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“bb”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。
 

这只是我对今日份学习的分享

原版博客在这里icon-default.png?t=N7T8https://blog.csdn.net/qq_37120563/article/details/121640676?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169789629516800222869371%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169789629516800222869371&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-121640676-null-null.142%5Ev96%5Epc_search_result_base2&utm_term=StringBuffer%E4%B8%BA%E4%BB%80%E4%B9%88%E6%95%88%E7%8E%87%E6%AF%94String%20%E9%AB%98&spm=1018.2226.3001.4187

这篇关于为什么StringBuffer比String在拼接的时候效率高?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/351719

相关文章

如何解决mysql出现Incorrect string value for column ‘表项‘ at row 1错误问题

《如何解决mysql出现Incorrectstringvalueforcolumn‘表项‘atrow1错误问题》:本文主要介绍如何解决mysql出现Incorrectstringv... 目录mysql出现Incorrect string value for column ‘表项‘ at row 1错误报错

python中字符串拼接的几种方法及优缺点对比详解

《python中字符串拼接的几种方法及优缺点对比详解》在Python中,字符串拼接是常见的操作,Python提供了多种方法来拼接字符串,每种方法有其优缺点和适用场景,以下是几种常见的字符串拼接方法,需... 目录1. 使用 + 运算符示例:优缺点:2. 使用&nbsjsp;join() 方法示例:优缺点:3

java String.join()的使用小结

《javaString.join()的使用小结》String.join()是Java8引入的一个实用方法,用于将多个字符串按照指定分隔符连接成一个字符串,本文主要介绍了javaString.join... 目录1. 方法定义2. 基本用法2.1 拼接多个字符串2.2 拼接集合中的字符串3. 使用场景和示例3

Golang中拼接字符串的6种方式性能对比

《Golang中拼接字符串的6种方式性能对比》golang的string类型是不可修改的,对于拼接字符串来说,本质上还是创建一个新的对象将数据放进去,主要有6种拼接方式,下面小编就来为大家详细讲讲吧... 目录拼接方式介绍性能对比测试代码测试结果源码分析golang的string类型是不可修改的,对于拼接字

C# string转unicode字符的实现

《C#string转unicode字符的实现》本文主要介绍了C#string转unicode字符的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1. 获取字符串中每个字符的 Unicode 值示例代码:输出:2. 将 Unicode 值格式化

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java实战之自助进行多张图片合成拼接

《Java实战之自助进行多张图片合成拼接》在当今数字化时代,图像处理技术在各个领域都发挥着至关重要的作用,本文为大家详细介绍了如何使用Java实现多张图片合成拼接,需要的可以了解下... 目录前言一、图片合成需求描述二、图片合成设计与实现1、编程语言2、基础数据准备3、图片合成流程4、图片合成实现三、总结前

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。