在大量字符串拼接操作时请使用StringBuffer解读

 更新时间:2025年08月15日 11:15:18   作者:奋力向前123  
StringBuffer为解决String不可变性及线程安全问题,提供可变缓冲区,支持高效拼接,其容量动态扩展,性能略低于StringBuilder,适用于多线程环境

StringBuffer的产生背景

StringBuffer是Java早期版本中引入的一个类,它的产生背景主要有以下几个原因:

1. 解决String不可变性问题

  • Java中的String对象是不可变的(immutable),每次修改String实际上都是创建新的String对象
  • 频繁修改字符串时会产生大量临时对象,影响性能
  • StringBuffer提供了可变的字符串缓冲区,可以在原对象上修改而不创建新对象

2. 线程安全需求

  • StringBuffer的方法都是同步的(synchronized),适合多线程环境下的字符串操作
  • 早期Java版本中,多线程编程较为常见,需要线程安全的字符串操作类

3. 性能优化

  • 在大量字符串拼接操作时,使用StringBuffer比直接使用"+"操作符更高效
  • StringBuffer内部维护了一个可扩展的字符数组,减少了内存分配和垃圾回收的开销

4. 历史原因

  • StringBuffer在Java 1.0中就已经存在
  • 后来(Java 5)又引入了非线程安全的StringBuilder,作为单线程环境下的替代方案

StringBuffer的设计反映了早期Java对线程安全的重视,但随着单线程应用场景的增加,StringBuilder因其更高的性能而成为更常用的选择。不过StringBuffer在多线程环境下仍然有其价值。

StringBuffer 详解

1. StringBuffer 概述

StringBuffer 是 Java 中用于可变字符串操作的类,位于 java.lang 包中。

它提供了比 String 更高效的字符串修改方式,适用于频繁修改字符串的场景,并且是线程安全的(方法使用 synchronized 修饰)。

主要特点:

  • 可变性:可以直接修改字符串内容,而不像 String 每次修改都生成新对象。
  • 线程安全:方法使用 synchronized 修饰,适合多线程环境。
  • 高效拼接:内部维护一个动态扩容的字符数组,减少内存分配和垃圾回收开销。

2. StringBuffer 的构造方法

构造方法说明
StringBuffer()构造一个初始容量为 16 的空缓冲区
StringBuffer(int capacity)构造指定初始容量的空缓冲区
StringBuffer(String str)构造一个初始内容为 str 的缓冲区,容量为 str.length() + 16

示例:

StringBuffer sb1 = new StringBuffer();         // 初始容量 16
StringBuffer sb2 = new StringBuffer(32);       // 初始容量 32
StringBuffer sb3 = new StringBuffer("Hello");  // 初始内容 "Hello",容量 21 (5 + 16)

3. StringBuffer 的常用方法

(1) 增:append()和insert()

方法说明
append(xxx)在末尾追加数据(支持多种类型:int、char、String 等)
insert(int offset, xxx)在指定位置插入数据

示例:

StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");       // "Hello World"
sb.insert(5, ",");         // "Hello, World"

(2) 删:delete()和deleteCharAt()

方法说明
delete(int start, int end)删除 [start, end) 之间的字符
deleteCharAt(int index)删除指定位置的字符

示例:

StringBuffer sb = new StringBuffer("Hello, World");
sb.delete(5, 7);          // "Hello World"(删除 ", ")
sb.deleteCharAt(5);       // "HelloWorld"(删除空格)

(3) 改:replace()和setCharAt()

方法说明
replace(int start, int end, String str)替换 [start, end) 之间的内容为 str
setCharAt(int index, char ch)替换指定位置的字符

示例:

StringBuffer sb = new StringBuffer("Hello World");
sb.replace(6, 11, "Java");  // "Hello Java"
sb.setCharAt(0, 'h');       // "hello Java"

(4) 查:charAt()、indexOf()、substring()

方法说明
charAt(int index)返回指定位置的字符
indexOf(String str)返回 str 第一次出现的索引
substring(int start, int end)返回 [start, end) 的子字符串

示例:

StringBuffer sb = new StringBuffer("Hello Java");
char ch = sb.charAt(6);          // 'J'
int index = sb.indexOf("Java");  // 6
String sub = sb.substring(6, 10); // "Java"

(5) 其他方法

方法说明
length()返回字符串长度
capacity()返回当前缓冲区容量
reverse()反转字符串
toString()转换为 String

示例:

StringBuffer sb = new StringBuffer("Hello");
System.out.println(sb.length());     // 5
System.out.println(sb.capacity());   // 21 (5 + 16)
sb.reverse();                       // "olleH"
String str = sb.toString();         // 转换为 String

4. StringBuffer 的扩容机制

默认初始容量:16(如果未指定)。

扩容规则

  • 当字符串长度超过当前容量时,自动扩容。
  • 新容量 = (旧容量 * 2) + 2
  • 如果仍然不够,则直接扩容到所需的最小容量。

示例:

StringBuffer sb = new StringBuffer();  // 初始容量 16
sb.append("1234567890123456");         // 刚好 16 字符,不扩容
sb.append("X");                        // 超过容量,扩容至 (16*2)+2 = 34
System.out.println(sb.capacity());     // 34

5. StringBuffer vs StringBuilder

对比项StringBufferStringBuilder
线程安全✅ 线程安全(synchronized)❌ 非线程安全
性能稍慢(同步开销)更快
适用场景多线程环境单线程环境

推荐使用:

  • 单线程:优先用 StringBuilder(更快)。
  • 多线程:用 StringBuffer(线程安全)。

总结

StringBuffer 适用于频繁修改字符串,比 String 更高效。

  • 线程安全,但性能略低于 StringBuilder
  • 扩容机制:默认 16,不够时 (oldCapacity * 2) + 2
  • 主要方法append()insert()delete()replace()reverse() 等。

适用场景:

  • 多线程环境下的字符串拼接、修改。
  • 需要频繁修改字符串内容时(如日志处理、动态 SQL 拼接)。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot中使用雪花算法生成雪花ID

    springboot中使用雪花算法生成雪花ID

    本文主要介绍了springboot中使用雪花算法生成雪花ID,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • SpringBoot实现嵌入式 Servlet容器

    SpringBoot实现嵌入式 Servlet容器

    传统的Spring MVC工程部署时需要将WAR文件放置在servlet容器的文档目录内,而Spring Boot工程使用嵌入式servlet容器省去了这一步骤,本文就来设置一下相关配置,感兴趣的可以了解一下
    2023-12-12
  • Java Map的排序实例详解

    Java Map的排序实例详解

    这篇文章主要介绍了 Java Map的排序实例详解的相关资料,希望通过本文大家能够掌握map的排序,需要的朋友可以参考下
    2017-09-09
  • Spring Cloud中Sentinel的两种限流模式介绍

    Spring Cloud中Sentinel的两种限流模式介绍

    如何使用Sentinel做流量控制呢?这篇文章就来为大家详细介绍了Spring Cloud中Sentinel的两种限流模式,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • java多线程导入excel的方法

    java多线程导入excel的方法

    最近项目写了poi导入excel数据到数据库,想把学到的知识用于实践,于是使用多线程方式导入excel,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • SpringBoot整合JWT实现登录认证与接口授权的全流程

    SpringBoot整合JWT实现登录认证与接口授权的全流程

    JWT作为一种轻量级的身份认证与授权方案,凭借其无状态、可跨域、易于扩展的特性,成为 Spring Boot 项目中实现认证授权的主流选择,本文将从环境搭建、核心实现到进阶优化,完整讲解 Spring Boot 整合 JWT 实现登录认证与接口授权的全流程,需要的朋友可以参考下
    2025-12-12
  • Java MyBatis返回两个字段作为Map的key和value问题

    Java MyBatis返回两个字段作为Map的key和value问题

    使用MyBatis查询两个字段并返回Map时,需要注意数据量和值的类型,直接返回Map会导致报错,使用@MapKey注解可以生成Map,但值是对象而不是直接值,为了解决这个问题,可以自定义一个Map结果处理器MapResultHandler
    2024-12-12
  • springboot之Validation参数校验详细解读

    springboot之Validation参数校验详细解读

    这篇文章主要介绍了springboot之Validation参数校验详细解读,本篇是关于springboot的参数校验知识,当然也适用其它java应用,读完本篇将学会基本的参数校验,自定义参数校验和分组参数校验,需要的朋友可以参考下
    2023-10-10
  • Java读取图片EXIF信息的方法

    Java读取图片EXIF信息的方法

    这篇文章主要介绍了Java读取图片EXIF信息的方法,较为详细的分析了图片EXIF信息的概念、功能及java读取EXIF信息的实现技巧,需要的朋友可以参考下
    2015-07-07
  • 浅谈Spring与SpringMVC父子容器的关系与初始化

    浅谈Spring与SpringMVC父子容器的关系与初始化

    这篇文章主要介绍了浅谈Spring与SpringMVC父子容器的关系与初始化,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08

最新评论