
🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录
- [✨Java字符串进阶:StringBuilder+StringJoiner|高效操作字符串的两大神器 吃透优化原理 ✅](#✨Java字符串进阶:StringBuilder+StringJoiner|高效操作字符串的两大神器 吃透优化原理 ✅)
-
- [📌 文章摘要](#📌 文章摘要)
-
- [🕒 阅读时长:约20分钟](#🕒 阅读时长:约20分钟)
- [✅ 适用人群 & 阅读重点](#✅ 适用人群 & 阅读重点)
- [📖 知识回顾(承上启下,直击痛点)](#📖 知识回顾(承上启下,直击痛点))
- [一、StringBuilder类核心精讲 🔥 字符串高效操作的核心工具](#一、StringBuilder类核心精讲 🔥 字符串高效操作的核心工具)
-
- [1.1 StringBuilder概述(必背核心)](#1.1 StringBuilder概述(必背核心))
- [1.2 StringBuilder构造方法(两种常用)](#1.2 StringBuilder构造方法(两种常用))
- [1.3 StringBuilder核心成员方法(开发必备)](#1.3 StringBuilder核心成员方法(开发必备))
- [1.4 核心方法实战示例(逐一讲解)](#1.4 核心方法实战示例(逐一讲解))
-
- [示例1:append() 添加数据(支持链式调用)](#示例1:append() 添加数据(支持链式调用))
- [示例2:reverse() 反转容器内容](#示例2:reverse() 反转容器内容)
- [示例3:length() 获取有效字符长度](#示例3:length() 获取有效字符长度)
- [示例4:toString() 转换为String对象](#示例4:toString() 转换为String对象)
- [1.5 StringBuilder底层扩容原理(笔试/面试必考)](#1.5 StringBuilder底层扩容原理(笔试/面试必考))
-
- [✔ 核心底层设计:字节数组存储](#✔ 核心底层设计:字节数组存储)
- [✔ 扩容规则(JDK8及以后)](#✔ 扩容规则(JDK8及以后))
- [✔ 扩容示例解析](#✔ 扩容示例解析)
- [1.6 StringBuilder经典实战:高效拼接字符串](#1.6 StringBuilder经典实战:高效拼接字符串)
- [二、StringJoiner类核心精讲 🎨 简洁美化的字符串拼接工具](#二、StringJoiner类核心精讲 🎨 简洁美化的字符串拼接工具)
-
- [2.1 StringJoiner概述(JDK8新特性)](#2.1 StringJoiner概述(JDK8新特性))
- [2.2 StringJoiner构造方法(两个核心)](#2.2 StringJoiner构造方法(两个核心))
- [2.3 StringJoiner核心成员方法(实用易记)](#2.3 StringJoiner核心成员方法(实用易记))
- [2.4 StringJoiner实战示例(场景化讲解)](#2.4 StringJoiner实战示例(场景化讲解))
- [三、StringBuilder vs StringJoiner 核心对比 📊 按需选择才是关键](#三、StringBuilder vs StringJoiner 核心对比 📊 按需选择才是关键)
- [四、核心考点提炼 📝 笔试/面试/开发必记](#四、核心考点提炼 📝 笔试/面试/开发必记)
-
- [✅ 核心考点1:StringBuilder核心特性](#✅ 核心考点1:StringBuilder核心特性)
- [✅ 核心考点2:StringBuilder高效的本质](#✅ 核心考点2:StringBuilder高效的本质)
- [✅ 核心考点3:StringJoiner高频易错点](#✅ 核心考点3:StringJoiner高频易错点)
- [✅ 核心考点4:三类字符串工具的选择原则](#✅ 核心考点4:三类字符串工具的选择原则)
- [✅ 经典面试题解析](#✅ 经典面试题解析)
- [✍️ 写在最后](#✍️ 写在最后)
- [💡 下期预告](#💡 下期预告)
✨Java字符串进阶:StringBuilder+StringJoiner|高效操作字符串的两大神器 吃透优化原理 ✅
📌 文章摘要
本文是Java字符串系列第二篇核心内容,承接上篇String类的"不可变"特性与痛点,系统讲解StringBuilder 和StringJoiner两个高频工具类,从类的核心特性、构造方法、成员方法到实战应用,全覆盖高效字符串操作的核心知识点。同时深入剖析StringBuilder底层扩容原理、源码设计,对比两个类的适用场景,解决String类拼接效率低、代码繁琐的问题。全文原理+实战结合,代码注释详尽、考点突出,零基础能快速掌握高效字符串操作方法,在校生可吃透笔试扩容考点,开发入门者能根据业务场景选择合适工具,是攻克Java字符串优化的必备篇章。
🕒 阅读时长:约20分钟
✅ 适用人群 & 阅读重点
▫️ Java零基础入门者 :重点看两个类的构造方法、核心方法示例,跟着敲写代码,掌握字符串高效拼接/拼接美化的基础用法。
▫️ 在校学生/笔试备考者 :吃透StringBuilder底层扩容原理、源码设计 ,这是面试/笔试高频必考考点,同时牢记两类的核心区别。
▫️ 开发入门夯实基础者 :聚焦方法的链式调用、返回值特性,理解为何这两个类能优化String的操作效率,掌握企业开发的编码规范。
▫️ 字符串操作薄弱者 :重点看场景化示例,理清"普通拼接"与"高效拼接"、"简单拼接"与"美化拼接"的使用差异。
▫️ 复习巩固者:直接看「核心考点提炼+类对比总结」,快速梳理核心用法与考点,查漏补缺。
📖 知识回顾(承上启下,直击痛点)
在Java字符串系列第一篇的学习中,我们吃透了String类的核心知识点,也发现了它的核心痛点 :字符串内容不可变,一旦进行拼接、修改等操作,就会在内存中创建大量冗余对象,不仅浪费内存空间,还会降低程序运行效率。
比如多次用+拼接字符串时,有变量参与的情况下会触发运行时多次创建对象,底层即使自动优化也无法彻底解决冗余问题。为了解决这个痛点,Java提供了StringBuilder 类作为字符串操作的优化工具,而在JDK8之后,又推出了StringJoiner 类,在拼接美化场景下让代码更简洁。本篇就来深入学习这两个"字符串高效操作神器",彻底解决String类的操作痛点。
一、StringBuilder类核心精讲 🔥 字符串高效操作的核心工具
1.1 StringBuilder概述(必背核心)
💡 StringBuilder可以看作一个可变的字符串容器,创建之后其内部的内容可以随意修改、添加、删除,不会像String类那样产生大量冗余对象。
- 核心特性 :内容可变 、操作高效,专为字符串的频繁拼接、反转等操作设计;
- 核心作用 :解决String类拼接效率低、内存浪费的问题,是开发中字符串批量操作的首选工具;
- 包路径 :
java.lang.StringBuilder,无需手动导包。
关键理解:String是不可变的字符串对象 ,而StringBuilder是存储字符串的可变容器,所有操作都在同一个容器中进行,不会创建多余对象。
1.2 StringBuilder构造方法(两种常用)
StringBuilder提供了两个核心构造方法,满足不同初始化需求,直接创建可操作的容器对象:
| 构造方法 | 说明 | 示例 |
|---|---|---|
public StringBuilder() |
创建一个空的字符串容器,无初始内容 | StringBuilder sb = new StringBuilder(); |
public StringBuilder(String str) |
创建一个字符串容器,初始化内容为指定字符串 | StringBuilder sb = new StringBuilder("abc"); |
简单示例:创建StringBuilder对象
java
public class StringBuilderCreateDemo {
public static void main(String[] args) {
// 空参构造:创建空容器
StringBuilder sb1 = new StringBuilder();
System.out.println("空容器内容:" + sb1); // 输出:空容器内容:(无内容)
// 带参构造:创建带初始内容的容器
StringBuilder sb2 = new StringBuilder("Java字符串");
System.out.println("带初始内容的容器:" + sb2); // 输出:带初始内容的容器:Java字符串
}
}
小技巧:Java对StringBuilder做了特殊处理,直接打印对象不会输出地址值,而是输出容器中的实际内容,无需手动调用方法获取,开发更便捷。
1.3 StringBuilder核心成员方法(开发必备)
StringBuilder提供了一系列专为字符串操作设计的方法,核心方法均支持链式调用,且修改操作直接作用于容器本身,以下是最常用的4个核心方法,必须熟练掌握:
| 方法 | 作用 | 特点 |
|---|---|---|
public StringBuilder append(任意类型) |
向容器中添加数据(字符串、数字、布尔等任意类型) | 返回对象本身,支持链式调用 |
public StringBuilder reverse() |
将容器中的所有内容反转 | 返回对象本身,支持链式调用 |
public int length() |
获取容器中有效字符的长度 | 与String类用法一致,返回int类型 |
public String toString() |
将StringBuilder容器转换为String对象 |
解决StringBuilder无法直接作为String类型使用的问题 |
1.4 核心方法实战示例(逐一讲解)
示例1:append() 添加数据(支持链式调用)
append()是StringBuilder最常用的方法,可添加任意数据类型,链式调用能让拼接代码更简洁,无需多次写对象名。
java
public class StringBuilderAppendDemo {
public static void main(String[] args) {
// 创建空容器
StringBuilder sb = new StringBuilder();
// 单个添加
sb.append("Hello");
sb.append(" ");
sb.append("Java");
System.out.println(sb); // 输出:Hello Java
// 链式调用(推荐,代码更简洁)
sb.append("\n").append(123).append(" ").append(true).append(" ").append(3.14);
System.out.println(sb); // 输出:Hello Java
// 123 true 3.14
}
}
核心要点:append()返回对象本身,所以才能实现链式调用,这是StringBuilder的核心设计之一。
示例2:reverse() 反转容器内容
专为字符串反转设计,一行代码实现,比手动用String类反转更高效、更简洁。
java
public class StringBuilderReverseDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("得鹿梦鱼");
// 反转内容
sb.reverse();
System.out.println(sb); // 输出:鱼梦鹿得
// 链式调用:添加+反转
StringBuilder sb2 = new StringBuilder();
sb2.append("123456").reverse();
System.out.println(sb2); // 输出:654321
}
}
示例3:length() 获取有效字符长度
用法与String类的length()方法完全一致,返回容器中实际存储的字符个数,而非容器的底层容量。
java
public class StringBuilderLengthDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("abc");
sb.append(123).append(true);
// 获取有效长度
int len = sb.length();
System.out.println("容器内容:" + sb); // 输出:abc123true
System.out.println("有效字符长度:" + len); // 输出:有效字符长度:9
}
}
示例4:toString() 转换为String对象
StringBuilder是容器 ,并非String类型,当需要将其作为String类型使用(如传入要求String参数的方法)时,需通过toString()转换,转换后得到一个新的String对象。
java
public class StringBuilderToStringDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("Java").append("字符串精讲");
// 转换为String类型
String str = sb.toString();
System.out.println("转换后的String:" + str); // 输出:Java字符串精讲
System.out.println("字符串长度:" + str.length()); // 输出:字符串长度:7
}
}
1.5 StringBuilder底层扩容原理(笔试/面试必考)
这是StringBuilder的核心考点,理解扩容原理能让你从"会用"升级为"懂原理",彻底吃透这个类的设计思想。
✔ 核心底层设计:字节数组存储
StringBuilder的底层是一个可变的字节数组(用于存储字符的ASCII值),所有添加的内容最终都会存入这个数组,其扩容逻辑围绕这个数组展开:
- 默认初始容量 :创建空参的StringBuilder时,底层会默认创建一个长度为16的字节数组;
- 带参构造容量 :创建
new StringBuilder("abc")时,底层数组容量为初始字符串长度 + 16(如"abc"长度3,容量为19); - 容量与长度的区别 :
- 容量:底层数组的总长度(可存储的最大字符数,开发者无需关心);
- 长度 :容器中实际存储的字符数(通过
length()获取)。
✔ 扩容规则(JDK8及以后)
当通过append()添加内容,实际长度超过底层数组容量 时,会触发自动扩容,扩容规则分三步:
- 若新增后长度 ≤ 原容量×2+2 → 扩容为原容量×2+2(默认初始16,第一次扩容为34);
- 若新增后长度 > 原容量×2+2 → 直接扩容为实际需要的长度(按需扩容,避免内存浪费);
- 扩容时会创建新的字节数组,将原数组的内容复制到新数组,后续操作都在新数组中进行。
✔ 扩容示例解析
java
// 空参构造,初始容量16,长度0
StringBuilder sb = new StringBuilder();
// 添加16个字符,长度16,未超容量,不扩容
sb.append("1234567890123456");
// 再添加1个字符,长度17>16,触发扩容→新容量34
sb.append("7");
// 再添加20个字符,长度37>34,触发扩容→新容量37(按需扩容)
sb.append("12345678901234567890");
核心总结:StringBuilder高效的本质是在一个可变数组中完成所有操作,仅在容量不足时触发一次扩容,远少于String类拼接时的对象创建次数。
1.6 StringBuilder经典实战:高效拼接字符串
对比String类和StringBuilder类的拼接效果,直观感受后者的高效性,这也是开发中的经典场景。
java
public class StringBuilderPractice {
public static void main(String[] args) {
// 场景:拼接1-100的数字,对比效率(此处直观展示代码,效率差异大数据量更明显)
// 方式1:String类拼接(有变量,多次创建对象)
String str = "";
for (int i = 1; i <= 10; i++) {
str += i;
}
System.out.println("String拼接:" + str); // 输出:String拼接:12345678910
// 方式2:StringBuilder拼接(单容器,无冗余对象)
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10; i++) {
sb.append(i);
}
String result = sb.toString();
System.out.println("StringBuilder拼接:" + result); // 输出:StringBuilder拼接:12345678910
}
}
开发规范:只要涉及多次字符串拼接(尤其是循环中),一律使用StringBuilder,这是企业开发的通用规范。
二、StringJoiner类核心精讲 🎨 简洁美化的字符串拼接工具
2.1 StringJoiner概述(JDK8新特性)
💡 StringJoiner与StringBuilder一样,也是一个可变的字符串容器 ,内容创建后可修改,核心优势是:在拼接多个字符串时,能自动添加分隔符、前缀、后缀,让代码更简洁,无需手动拼接分隔符。
- 核心特性:内容可变、拼接美化、代码简洁;
- 出现版本:JDK 8及以后才支持,使用前需确认JDK版本;
- 包路径 :
java.util.StringJoiner,需要手动导包(高频易错点); - 核心作用 :替代StringBuilder做带分隔符的拼接 (如数组转字符串
[1,2,3]、拼接多个参数a-b-c),代码更简洁。
2.2 StringJoiner构造方法(两个核心)
StringJoiner的构造方法直接关联分隔符、前缀、后缀,这是它与StringBuilder的核心区别,两个构造方法满足不同美化需求:
| 构造方法 | 说明 | 示例 | 拼接效果 |
|---|---|---|---|
public StringJoiner(CharSequence delimiter) |
创建空容器,指定分隔符(多个内容之间的符号) | new StringJoiner("---") |
a---b---c |
public StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) |
创建空容器,指定分隔符+前缀+后缀 | new StringJoiner(", ", "[", "]") |
[1, 2, 3] |
小提示:
CharSequence是String的父接口,传入字符串直接即可。
2.3 StringJoiner核心成员方法(实用易记)
StringJoiner的方法与StringBuilder相似,核心方法同样支持链式调用,且贴合拼接美化的业务场景,常用方法有3个:
| 方法 | 作用 | 特点 |
|---|---|---|
public StringJoiner add(CharSequence newElement) |
向容器中添加字符串内容 | 返回对象本身,支持链式调用 |
public int length() |
获取容器中有效字符的总长度(包含分隔符、前缀、后缀) | 返回int类型 |
public String toString() |
将容器内容转换为String对象 | 最终拼接结果,开发中必用 |
2.4 StringJoiner实战示例(场景化讲解)
示例1:仅指定分隔符拼接
适用于简单的带分隔符拼接场景,如拼接多个名称、编号。
java
import java.util.StringJoiner; // 必须导包
public class StringJoinerDemo1 {
public static void main(String[] args) {
// 创建容器,指定分隔符为顿号
StringJoiner sj = new StringJoiner("、");
// 添加内容(链式调用)
sj.add("Java").add("Python").add("C++").add("Go");
// 转换为String并打印
System.out.println(sj.toString()); // 输出:Java、Python、C++、Go
}
}
示例2:指定分隔符+前缀+后缀拼接
这是StringJoiner的核心使用场景,如数组转格式化字符串、集合元素拼接,无需手动添加前缀后缀和分隔符。
java
import java.util.StringJoiner;
public class StringJoinerDemo2 {
public static void main(String[] args) {
// 创建容器:分隔符为逗号+空格,前缀为[,后缀为]
StringJoiner sj = new StringJoiner(", ", "[", "]");
// 循环添加1-5的数字
for (int i = 1; i <= 5; i++) {
sj.add(String.valueOf(i)); // 把int转为String
}
// 打印结果
System.out.println(sj); // 输出:[1, 2, 3, 4, 5]
// 获取总长度([+1+,+ +2+,+ +3+,+ +4+,+ +5+] → 共15)
System.out.println("总长度:" + sj.length()); // 输出:总长度:15
}
}
示例3:对比StringBuilder实现相同效果
通过对比,直观感受StringJoiner的代码简洁性,实现同样的[1,2,3]效果,StringBuilder需要手动拼接分隔符、前缀后缀。
java
import java.util.StringJoiner;
public class StringJoinerCompare {
public static void main(String[] args) {
// 方式1:StringJoiner实现(简洁,一行构造,自动拼接)
StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("1").add("2").add("3");
System.out.println("StringJoiner:" + sj); // 输出:[1, 2, 3]
// 方式2:StringBuilder实现(繁琐,手动拼接所有符号)
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append("1").append(", ").append("2").append(", ").append("3");
sb.append("]");
System.out.println("StringBuilder:" + sb); // 输出:[1, 2, 3]
}
}
核心结论:带分隔符的格式化拼接用StringJoiner,普通拼接/反转用StringBuilder,各司其职。
三、StringBuilder vs StringJoiner 核心对比 📊 按需选择才是关键
很多初学者会混淆这两个类,其实它们的核心定位不同,一个主打通用高效 ,一个主打美化简洁,以下是核心对比,帮你快速选择:
| 对比维度 | StringBuilder | StringJoiner |
|---|---|---|
| 出现版本 | JDK5及以后 | JDK8及以后 |
| 包路径/导包 | java.lang,无需导包 | java.util,需要导包 |
| 核心定位 | 通用的字符串高效操作工具 | 带分隔符的格式化拼接工具 |
| 核心优势 | 支持拼接、反转等所有操作,功能全面 | 自动添加分隔符/前缀/后缀,代码简洁 |
| 底层实现 | 基于字节数组,支持扩容 | 底层封装了StringBuilder,本质是其封装类 |
| 适用场景 | 1. 任意字符串拼接(尤其是循环) 2. 字符串反转 3. 无格式要求的批量操作 | 1. 带分隔符的拼接(如a-b-c) 2. 带前后缀的格式化拼接(如[1,2,3]) 3. 数组/集合元素的格式化输出 |
| 方法丰富度 | 方法多,功能全面 | 方法少,仅聚焦拼接美化 |
关键知识点:StringJoiner底层其实是封装了StringBuilder,它的高效性本质来自StringBuilder,只是做了上层的美化封装。
四、核心考点提炼 📝 笔试/面试/开发必记
✅ 核心考点1:StringBuilder核心特性
- 内容可变,是存储字符串的容器,而非不可变对象;
- 底层是字节数组,默认初始容量16,容量不足时自动扩容,扩容规则为原容量×2+2 或按需扩容;
- 所有修改方法(append、reverse)都返回对象本身,支持链式调用;
- 需通过
toString()转换为String类型才能作为String参数使用。
✅ 核心考点2:StringBuilder高效的本质
在单个可变容器中完成所有操作,仅在容量不足时触发一次扩容,避免了String类拼接时的多次对象创建,节省内存且提高效率。
✅ 核心考点3:StringJoiner高频易错点
- JDK8及以后才支持,使用前确认版本;
- 位于
java.util包,必须手动导包(笔试编译报错高频点); - length()返回的长度包含分隔符、前缀、后缀,并非仅实际内容长度。
✅ 核心考点4:三类字符串工具的选择原则
- 简单字符串使用(无修改/拼接)→ 直接用String类(直接赋值,复用串池);
- 字符串拼接/反转/批量修改(无格式要求)→ 用StringBuilder(高效通用);
- 带分隔符/前后缀的格式化拼接→ 用StringJoiner(代码简洁);
- 循环中拼接字符串→ 绝对不用String类,优先用StringBuilder/StringJoiner。
✅ 经典面试题解析
面试题:StringBuilder的初始容量和扩容规则是什么?
答案:
- 空参构造的StringBuilder底层默认创建长度16的字节数组,初始容量为16;
- 带参构造的容量为初始字符串长度 + 16;
- 当实际存储长度超过容量时触发扩容:若新增长度≤原容量×2+2,扩容为原容量×2+2;若新增长度>原容量×2+2,直接扩容为实际需要的长度;
- 扩容时会创建新数组,复制原数组内容,后续操作在新数组中进行。
✍️ 写在最后
本篇我们吃透了Java字符串操作的两大核心优化工具------StringBuilder和StringJoiner,解决了String类"不可变"带来的效率痛点。从核心用法到底层原理,从场景实战到类的对比,我们理清了三者的定位与选择原则:String是基础,StringBuilder是通用优化工具,StringJoiner是格式化拼接的专用工具,三者各司其职,配合使用才能让字符串操作既高效又简洁。
StringBuilder的底层扩容原理是笔试/面试的高频考点,一定要理解透彻,而非死记硬背;而StringJoiner的核心是记住其导包要求、构造方法 和适用场景,避免开发中出现编译错误或代码冗余。
作为字符串系列的第二篇,我们完成了"高效操作"的核心学习,下一篇将聚焦字符串底层原理深度剖析,包括String拼接的编译期/运行时优化、三大类的内存对比、经典面试题深度解析,实现从"懂用法"到"通原理"的终极跨越。
Java的字符串知识看似简单,实则暗藏诸多考点,只有把每个细节学透,才能在笔试和开发中少踩坑。愿你继续保持对底层原理的探索,夯实每一个基础知识点!✨
💡 下期预告
Java字符串精讲(三):字符串底层原理深度剖析+经典面试题全解|吃透编译期优化/内存机制/高频坑点,实现知识闭环!
本文为Java字符串系列第二篇,案例均经过实测可运行,代码规范贴合企业开发。如果对你有帮助,欢迎点赞+收藏+关注,后续会持续更新Java字符串核心知识点与实战案例!有问题可在评论区留言,逐一回复解答~