Java StringBuffer 和 StringBuilder 类

Java StringBuffer 和 StringBuilder 类

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
在这里插入图片描述
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
在这里插入图片描述

编译运行输出如下

在这里插入图片描述


关于StringBuilder 线程安全

在 Java 中,StringBuilder 和 StringBuffer 都用于在内存中构建(或修改)字符串,但是它们的主要区别在于线程安全性。

  1. 线程安全性:
    StringBuffer:是线程安全的。这意味着当你从多个线程访问或修改同一个 StringBuffer 对象时,你不需要担心数据不一致或损坏。这是因为 StringBuffer 的大多数方法(如 append(), insert(), delete(), replace() 等)都是同步的(synchronized)。但是,这种线程安全性是以牺牲性能为代价的,因为同步方法需要额外的开销来确保线程安全。
    StringBuilder:不是线程安全的。这意味着如果你从多个线程访问或修改同一个 StringBuilder 对象,你可能会遇到数据不一致或损坏的问题。但是,由于没有同步开销,StringBuilder 通常比 StringBuffer 更快。
  2. 性能:
    由于 StringBuilder 没有同步开销,所以在单线程环境中,它通常比 StringBuffer 更快。但是,在多线程环境中,你可能需要额外的同步机制来确保线程安全,这可能会降低性能。
  3. 使用场景:
    如果你在单线程环境中工作,并且不需要线程安全性,那么你应该使用 StringBuilder。这将给你更好的性能。
    如果你在多线程环境中工作,并且需要线程安全性,那么你应该使用 StringBuffer。但是,请注意,如果你知道你的代码将始终从单个线程访问 StringBuilder,即使你在多线程环境中,你也可以安全地使用 StringBuilder。

StringBuffer 方法

以下是 StringBuffer 类支持的主要方法:

方法描述
public StringBuffer append(String s)将指定的字符串追加到此字符序列。
public StringBuffer reverse()将此字符序列用其反转形式取代。
public delete(int start, int end)移除此序列的子字符串中的字符。
public insert(int offset, int i)将 int 参数的字符串表示形式插入此序列中。
insert(int offset, String str)将 str 参数的字符串插入此序列中。
replace(int start, int end, String str)使用给定 String 中的字符替换此序列的子字符串中的字符。

以下列表列出了 StringBuffer 类的其他常用方法:

方法描述
int capacity()返回当前容量。
char charAt(int index)返回此序列中指定索引处的 char 值。
void ensureCapacity(int minimumCapacity)确保容量至少等于指定的最小值。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此序列复制到目标字符数组 dst。
int indexOf(String str)返回第一次出现的指定子字符串在该字符串中的索引。
int indexOf(String str, int fromIndex)从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。
int lastIndexOf(String str)返回最右边出现的指定子字符串在此字符串中的索引。
int lastIndexOf(String str, int fromIndex)返回 String 对象中子字符串最后出现的位置。
int length()返回长度(字符数)。
void setCharAt(int index, char ch)将给定索引处的字符设置为 ch。
void setLength(int newLength)设置字符序列的长度。
CharSequence subSequence(int start, int end)返回一个新的字符序列,该字符序列是此序列的子序列。
String substring(int start)返回一个新的 String,它包含此字符序列当前所包含的字符子序列。
String substring(int start, int end)返回一个新的 String,它包含此序列当前所包含的字符子序列。
String toString()返回此序列中数据的字符串表示形式。

JAVA 中的 StringBuilder 和 StringBuffer 适用的场景是什么?

最简单的回答是,stringbuffer 基本没有适用场景,你应该在所有的情况下选择使用 stringbuiler,除非你真的遇到了一个需要线程安全的场景,如果遇到了,请务必在这里留言通知我。

然后,补充一点,关于线程安全,即使你真的遇到了这样的场景,很不幸的是,恐怕你仍然有 99.99…99% 的情况下没有必要选择 stringbuffer,因为 stringbuffer 的线程安全,仅仅是保证 jvm 不抛出异常顺利的往下执行而已,它可不保证逻辑正确和调用顺序正确。大多数时候,我们需要的不仅仅是线程安全,而是锁。

最后,为什么会有 stringbuffer 的存在,如果真的没有价值,为什么 jdk 会提供这个类?答案太简单了,因为最早是没有 stringbuilder 的,sun 的人不知处于何种愚蠢的考虑,决定让 stringbuffer 是线程安全的,然后大约 10 年之后,人们终于意识到这是一个多么愚蠢的决定,意识到在这 10 年之中这个愚蠢的决定为 java 运行速度慢这样的流言贡献了多大的力量,于是,在 jdk1.5 的时候,终于决定提供一个非线程安全的 stringbuffer 实现,并命名为 stringbuilder。顺便,javac 好像大概也是从这个版本开始,把所有用加号连接的 string 运算都隐式的改写成 stringbuilder,也就是说,从 jdk1.5 开始,用加号拼接字符串已经没有任何性能损失了。

如诸多评论所指出的,我上面说,"用加号拼接字符串已经没有任何性能损失了"并不严谨,严格的说,如果没有循环的情况下,单行用加号拼接字符串是没有性能损失的,java 编译器会隐式的替换成 stringbuilder,但在有循环的情况下,编译器没法做到足够智能的替换,仍然会有不必要的性能损耗,因此,用循环拼接字符串的时候,还是老老实实的用 stringbuilder 吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qayrup

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值