Java字符串拼接的6种方式对比:性能与场景详解
Java中字符串拼接有多种实现手段,包括最常用的+号、StringBuilder、StringBuffer,以及JDK1.8新增的String.join和StringJoiner,还有第三方库如Apache Commons Lang3的StringUtils。不同方式在性能、线程安全和代码可读性上各有优劣。
方式一:使用 + 运算符
这是Java中最直观且最常见的字符串拼接方式。对于简单的字符串连接,编译器通常会进行优化(如转换为StringBuilder操作),但在循环等复杂场景中直接使用+可能导致性能问题。
String aa = "今天";
String bb = "明天";
System.out.println(aa + bb);
方式二:使用 StringBuilder 和 StringBuffer
在处理字符串拼接时,StringBuilder和StringBuffer是两种核心类。StringBuffer是大哥,其大部分方法都经过 synchronized 修饰,因此它是线程安全的,但同步机制带来了额外的开销,导致效率相对 StringBuilder 较低。StringBuilder 非线程安全,适用于单线程环境下的频繁拼接,性能更优。
String aa = "今天";
String bb = "明天";
StringBuilder sber = new StringBuilder();
StringBuffer sbf = new StringBuffer();
// StringBuilder 示例
sber.append(aa).append(bb);
System.out.println(sber.toString());
// StringBuffer 示例
sbf.append(aa).append(bb);
System.out.println(sbf.toString());
方式三:使用 String.concat() 方法
String类的concat()方法用于连接两个字符串。需要注意以下特性:
- 空指针风险:如果参与拼接的目标字符串为
null,会抛出NullPointerException。 - 空字符串处理:如果拼接的是空字符串(
""),该方法的效率通常优于+号,因为它直接复用内部字符数组。 - 大量拼接限制:若拼接字符串非常多,因每次调用都会创建新的String对象,开销较大,效率会下降。
String aa = "今天";
String bb = "明天";
String concatResult = aa.concat(bb);
System.out.println(concatResult);
方式四:使用 String.join() (JDK 1.8)
JDK 1.8在String类中增加了一个静态方法join,主要用于将多个字符串通过指定的连接符合并。第一个参数为分隔符,后续参数为待拼接的字符串序列。这种方式代码简洁,适合已知数量元素的情况。
String aa = "今天";
String bb = "明天";
String joinResult = String.join("-", aa, bb);
System.out.println(joinResult);
方式五:使用 StringJoiner (JDK 1.8)
StringJoiner位于 java.util包中,专为构造由分隔符重新连接的字符序列而设计。它支持设置前缀和后缀,能够处理动态添加字符串的场景,且在合并操作时具有较好的性能表现。
核心源码逻辑分析:
StringJoiner内部管理一个StringBuilder(value)。初始化时仅记录前缀、分隔符和后缀,并不会立即构建完整字符串。每当调用 add() 时,先通过 prepareBuilder() 判断:if 已有内容则追加分隔符,else 则追加前缀并新建StringBuilder。值得注意的是,toString() 方法在返回结果前才会追加后缀,从而避免在中间过程中重复分配内存,提升 length() 等方法调用的效率。
// StringJoiner 关键代码片段
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
Objects.requireNonNull(prefix, "The prefix must not be null");
Objects.requireNonNull(delimiter, "The delimiter must not be null");
Objects.requireNonNull(suffix, "The suffix must not be null");
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
this.emptyValue = this.prefix + this.suffix;
}
private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter); // 追加分隔符
} else {
value = new StringBuilder().append(prefix); // 首次添加前缀
}
return value;
}
实战示例:
String aa = "今天";
String bb = "明天";
// 设置分隔符为":",前缀为"[",后缀为"]"
StringJoiner sj = new StringJoiner(":", "[", "]");
sj.add(aa).add(bb);
System.out.println(sj.toString()); // 输出: [今天:明天]
方式六:使用 Apache Commons Lang3 的 StringUtils
在大型项目实战中,经常需要处理集合或数组的拼接。org.apache.commons.lang3.StringUtils 提供了丰富的工具方法。相较于标准库,它更加健壮,能有效防止 NullPointerException,并且对数组元素的拼接非常友好。
String ids[] = {"1","2","3"};
// 混合拼接多个对象
System.out.println(StringUtils.join("a", "b", "-", "124"));
// 数组拼接,指定分隔符为逗号
String joinArray = StringUtils.join(ids, ",");
System.out.println(joinArray); // 输出: 1,2,3
场景选择建议
| 方式 | 适用场景 | 注意事项 |
|---|---|---|
+ |
简单的常量或少数变量拼接 | 循环内慎用,注意编译器优化 |
StringBuilder |
单线程下大量字符串拼接 | 非线程安全,需自行保证并发安全 |
StringBuffer |
多线程环境下需要线程安全的拼接 | 性能低于StringBuilder,同步开销大 |
String.join |
固定数量的字符串以统一分隔符连接 | 不支持动态添加元素,不支持前后缀 |
StringJoiner |
需要前缀/后缀,或动态添加元素的场景 | JDK 1.8+,内部基于StringBuilder优化 |
StringUtils |
复杂数组/集合处理,需防Null异常 | 依赖第三方Jar包 |
以上就是Java中字符串常见拼接方式的详细内容,更多关于Java字符串拼接优化的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









