1. 简介
Java 提供了多种用于 字符串拼接(String Concatenation) 的方法和类。
本文将深入探讨几种常用的方式,并指出一些常见的误区与不当实践。如果你已经对基础语法有所了解,那么可以直接跳过啰嗦的部分 ✅。
2. StringBuilder
先来说说 StringBuilder
,这个类在 Java 字符串操作中扮演着非常重要的角色。
它内部维护一个可变字符数组,通过构造函数我们可以预设其初始容量(例如 100),这样可以避免频繁扩容带来的性能损耗:
StringBuilder stringBuilder = new StringBuilder(100);
stringBuilder.append("Baeldung");
stringBuilder.append(" is");
stringBuilder.append(" awesome");
assertEquals("Baeldung is awesome", stringBuilder.toString());
⚠️ 注意:StringBuffer
是 StringBuilder
的线程安全版本,但由于其构建模式,在多线程环境下并不推荐使用。虽然单个方法调用是线程安全的,但多个连续调用却不是 ❌。
3. 加号运算符(+)
加号 +
是最直观的拼接方式,适用于少量、静态的字符串拼接场景:
String myString = "The " + "quick " + "brown " + "fox...";
assertEquals("The quick brown fox...", myString);
但是要注意,这种方式在编译时会被转换为一系列 StringBuilder.append()
调用。因此,如果混用 +
和 StringBuilder
拼接,容易造成代码风格混乱 ❌。
此外,在循环中大量使用 +
拼接字符串是非常低效的,因为每次拼接都会创建一个新的 String
对象,而 String
是不可变的 ⚠️。
4. String 类的方法
String
类本身也提供了多个拼接相关的方法。
4.1. String.concat()
concat()
方法是拼接字符串时最直接的选择之一。它可以链式调用,返回一个新的 String
实例:
String myString = "Both".concat(" fickle")
.concat(" dwarves")
.concat(" jinx")
.concat(" my")
.concat(" pig")
.concat(" quiz");
assertEquals("Both fickle dwarves jinx my pig quiz", myString);
这种链式写法简洁明了,适合做固定结构的字符串组装。
4.2. String.format()
String.format()
则更加强大,支持格式化模板注入各种对象:
String myString = String.format("%s %s %.2f %s %s, %s...", "I",
"ate",
2.5056302,
"blueberry",
"pies",
"oops");
assertEquals("I ate 2.51 blueberry pies, oops...", myString);
格式化字符串中的 %s
、%.2f
等占位符会自动替换为传入的参数,非常适合日志或输出语句。
4.3. String.join()(Java 8+)
从 Java 8 开始,String.join()
成为了拼接数组或集合中元素的好帮手。它接受一个分隔符,并自动将所有元素连接起来:
String[] strings = {"I'm", "running", "out", "of", "pangrams!"};
String myString = String.join(" ", strings);
assertEquals("I'm running out of pangrams!", myString);
相比手动拼接,这种方式更优雅、不易出错 ✅。
5. StringJoiner(Java 8+)
StringJoiner
是对 String.join()
功能的进一步封装,适用于需要动态添加字符串的场景:
StringJoiner fruitJoiner = new StringJoiner(", ");
fruitJoiner.add("Apples");
fruitJoiner.add("Oranges");
fruitJoiner.add("Bananas");
assertEquals("Apples, Oranges, Bananas", fruitJoiner.toString());
相比先构造数组再拼接,StringJoiner
更灵活,而且支持设置前缀和后缀,比如括号、引号等。
想深入了解的话可以看我们之前的文章《Java StringJoiner 详解》。
6. Arrays.toString()
说到数组,不得不提 Arrays.toString()
这个工具方法。它可以方便地打印数组内容,自动调用每个元素的 toString()
方法:
String[] myFavouriteLanguages = {"Java", "JavaScript", "Python"};
String toString = Arrays.toString(myFavouriteLanguages);
assertEquals("[Java, JavaScript, Python]", toString);
不过它的输出格式固定为 [元素1, 元素2, ...]
格式,无法自定义 ❌。
7. Collectors.joining()(Java 8+)
最后,如果你在使用 Stream API,那么 Collectors.joining()
就是你最好的朋友。它可以轻松把流中的元素拼接成一个字符串:
List<String> awesomeAnimals = Arrays.asList("Shark", "Panda", "Armadillo");
String animalString = awesomeAnimals.stream().collect(Collectors.joining(", "));
assertEquals("Shark, Panda, Armadillo", animalString);
这种方式不仅简洁,还能结合 filter、map 等流操作进行复杂的数据处理 ✅。
8. 总结
在这篇文章中,我们一起回顾了 Java 中多种字符串拼接方式的特点和适用场景:
方法 | 是否推荐 | 适用场景 |
---|---|---|
+ 运算符 |
⚠️ 少量拼接可用 | 静态文本拼接 |
StringBuilder |
✅ 推荐 | 多次拼接、循环拼接 |
String.concat() |
✅ 可用 | 简单链式拼接 |
String.format() |
✅ 推荐 | 格式化输出 |
String.join() |
✅ 推荐 | 数组/集合拼接 |
StringJoiner |
✅ 推荐 | 动态拼接、带前后缀 |
Arrays.toString() |
⚠️ 输出调试信息可用 | 打印数组 |
Collectors.joining() |
✅ 推荐 | 流式拼接 |
如需获取文中示例代码,请访问 GitHub 仓库:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-string-operations-2