首页 Java java教程 辨析Java中的String与StringBuffer及StringBuilder字符串类

辨析Java中的String与StringBuffer及StringBuilder字符串类

Jan 22, 2017 am 10:06 AM

1 String
String:字符串常量,字符串长度不可变。

2 StringBuffer
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
Java.lang.StringBuffer线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将?定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

3 StringBuilder
StringBuilder:字符串变量(非线程安全)。
java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因?在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
在大部分情况下,StringBuilder > StringBuffer。

4 三者区别
String 类型和StringBuffer的主要性能区别:String是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因?每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,例如:

String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
登录后复制

生成 String S1 对象的速度并不比 StringBuffer慢。其实在 JVM 里,自动做了如下转换:

String S1 = “This is only a” + “ simple” + “test”;
登录后复制

JVM直接把上述语句当作:

String S1 = “This is only a simple test”;
登录后复制

所以速度很快。但要注意的是,如果拼接的字符串来自另外的String对象的话,JVM就不会自动转换了,速度也就没那么快了,例如:

String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
登录后复制

这时候,JVM 会规规矩矩的按照原来的方式去做。
在大部分情况下,StringBuffer > String。

4.StringBuffer和StringBuilder
二者几乎没什么区别,基本都是在调用父类的各个方法,一个重要的区别就是StringBuffer是线程安全的,内部的大多数方法前面都有关键字synchronized,这样就会有一定的性能消耗,StringBuilder是非线程安全的,所以效率要高些。

public static void main(String[] args) throws Exception {
    String string = "0";
    int n = 10000;
    long begin = System.currentTimeMillis();
    for (int i = 1; i < n; i++) {
      string += i;
    }
    long end = System.currentTimeMillis();
    long between = end - begin;
    System.out.println("使用String类耗时:" + between+"ms");
  
    int n1 = 10000;
    StringBuffer sb = new StringBuffer("0");
    long begin1 = System.currentTimeMillis();
    for (int j = 1; j < n1; j++) {
      sb.append(j);
    }
    long end1 = System.currentTimeMillis();
    long between1 = end1 - begin1;
    System.out.println("使用StringBuffer类耗时:" + between1+"ms");
  
    int n2 = 10000;
    StringBuilder sb2 = new StringBuilder("0");
    long begin2 = System.currentTimeMillis();
    for (int k = 1; k < n2; k++) {
      sb2.append(k);
    }
    long end2 = System.currentTimeMillis();
    long between2 = end2 - begin2;
    System.out.println("使用StringBuilder类耗时:" + between2+"ms");
  }
登录后复制

输出:

使用String类耗时:982ms
使用StringBuffer类耗时:2ms
使用StringBuilder类耗时:1ms
登录后复制

虽然这个数字每次执行都不一样,而且每个机子的情况也不一样,但是有几点是确定的,String类消耗的明显比另外两个多得多。还有一点就是,StringBuffer要比StringBuilder消耗的多,尽管相差不明显。


5 使用策略
(1)基本原则:如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
(2)不要使用String类的"+"来进行频繁的拼接,因?那?的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。举个例子:在使用String 的时候,拼接字符串时使用“+”在JVM上形成临时的StringBuffer对象,同时在每一个字符串上都建立一个对象,拼接了两个字符串一共需要创建4个对象!(一个保存结果的String,两个字符串对象,一个临时的StringBuffer对象)。而使用StringBuffer的话,只需创建2个对象!一个StringBuffer对象和保存最后结果的的String对象 。
(3)?了获得更好的性能,在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它们的容量。当然,如果你操作的字符串长度不超过 16 个字符就不用了。不指定容量会显著降低性能。
(4)StringBuilder一般使用在方法内部来完成类似"+"功能,因?是线程不安全的,所以用完以后可以丢弃。StringBuffer主要用在全局变量中。
(5)相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer。

更多辨析Java中的String与StringBuffer及StringBuilder字符串类相关文章请关注PHP中文网!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

公司安全软件导致应用无法运行?如何排查和解决? 公司安全软件导致应用无法运行?如何排查和解决? Apr 19, 2025 pm 04:51 PM

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

如何使用MapStruct简化系统对接中的字段映射问题? 如何使用MapStruct简化系统对接中的字段映射问题? Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

如何优雅地获取实体类变量名构建数据库查询条件? 如何优雅地获取实体类变量名构建数据库查询条件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

如何将姓名转换为数字以实现排序并保持群组中的一致性? 如何将姓名转换为数字以实现排序并保持群组中的一致性? Apr 19, 2025 pm 11:30 PM

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? 使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名构建查询条件? Apr 19, 2025 pm 09:51 PM

在使用TKMyBatis进行数据库查询时,如何优雅地获取实体类变量名以构建查询条件,是一个常见的难题。本文将针...

Java对象如何安全地转换为数组? Java对象如何安全地转换为数组? Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

如何利用Redis缓存方案高效实现产品排行榜列表的需求? 如何利用Redis缓存方案高效实现产品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis缓存方案如何实现产品排行榜列表的需求?在开发过程中,我们常常需要处理排行榜的需求,例如展示一个�...

See all articles