Java字符串四大類(lèi)之String、StringBuffer、StringBuilder、StringJoiner詳解
前言
在 Java 開(kāi)發(fā)中,字符串操作是高頻場(chǎng)景,而 String、StringBuffer、StringBuilder、StringJoiner 這四個(gè)類(lèi)是處理字符串的核心工具。很多開(kāi)發(fā)者在日常使用中容易混淆它們的特性和適用場(chǎng)景,本文將從「核心區(qū)別」「構(gòu)造方法」「常用方法」「實(shí)戰(zhàn)示例」四個(gè)維度全面拆解,幫助大家系統(tǒng)掌握,方便后續(xù)復(fù)習(xí)查閱。
一、核心區(qū)別總覽(復(fù)習(xí)核心)
這四個(gè)類(lèi)的核心差異集中在「可變性」「線(xiàn)程安全」和「性能」上,是選擇使用場(chǎng)景的關(guān)鍵依據(jù)。用表格直觀呈現(xiàn):
| 類(lèi)名 | 可變性 | 線(xiàn)程安全 | 性能 | 底層實(shí)現(xiàn) | 核心適用場(chǎng)景 |
|---|---|---|---|---|---|
| String | 不可變(final 修飾) | 安全(無(wú)修改操作,天然線(xiàn)程安全) | 最低(頻繁拼接產(chǎn)生大量臨時(shí)對(duì)象) | JDK8 及之前:char[];JDK9+:byte[](節(jié)省內(nèi)存) | 字符串常量、少量不修改的字符串(如配置項(xiàng)、固定文本) |
| StringBuilder | 可變 | 不安全(無(wú)同步鎖) | 最高(無(wú)鎖 overhead) | 可變 char[] 數(shù)組 | 單線(xiàn)程環(huán)境下頻繁拼接/修改字符串(日常開(kāi)發(fā)首選) |
| StringBuffer | 可變 | 安全(方法加 synchronized 鎖) | 中等(比 StringBuilder 低 10%-20%) | 可變 char[] 數(shù)組 | 多線(xiàn)程環(huán)境下頻繁拼接/修改字符串(如多線(xiàn)程日志生成) |
| StringJoiner | 可變(封裝 StringBuilder) | 不安全(依賴(lài)底層 StringBuilder) | 與 StringBuilder 一致 | 內(nèi)部持有 StringBuilder 對(duì)象 | 帶分隔符的字符串拼接(如 a,b,c、[x,y,z],無(wú)需手動(dòng)處理分隔符) |
二、逐個(gè)拆解:構(gòu)造方法 + 常用方法
每個(gè)類(lèi)的構(gòu)造方法和常用方法是實(shí)際開(kāi)發(fā)的基礎(chǔ),下面逐個(gè)梳理
1. String(不可變字符串)
String 是 Java 最基礎(chǔ)的字符串類(lèi),一旦創(chuàng)建,內(nèi)容無(wú)法修改。所有“修改”操作(如 substring、replace)都會(huì)生成新的 String 對(duì)象。
(1)核心構(gòu)造方法
| 構(gòu)造方法 | 說(shuō)明 | 示例 |
|---|---|---|
| String() | 創(chuàng)建空字符串對(duì)象 | String str = new String(); |
| String(String original) | 通過(guò)已有字符串創(chuàng)建(復(fù)用內(nèi)容) | String str = new String(“hello”); |
| String(char[] value) | 通過(guò)字符數(shù)組創(chuàng)建 | char[] arr = {‘a’,‘b’,‘c’}; String str = new String(arr); |
| String(byte[] bytes) | 通過(guò)字節(jié)數(shù)組創(chuàng)建(使用默認(rèn)編碼) | byte[] bytes = “abc”.getBytes(); String str = new String(bytes); |
| String(byte[] bytes, String charsetName) | 通過(guò)字節(jié)數(shù)組+指定編碼創(chuàng)建 | String str = new String(bytes, “UTF-8”); |
(2)常用方法(必須掌握)
| 方法名 | 說(shuō)明 | 示例 | 返回結(jié)果 |
|---|---|---|---|
| int length() | 獲取字符串長(zhǎng)度 | “abc”.length() | 3 |
| char charAt(int index) | 獲取指定索引的字符(索引從 0 開(kāi)始) | “abc”.charAt(1) | ‘b’ |
| String substring(int start, int end) | 截取子串(左閉右開(kāi),end 不包含) | “abcde”.substring(1,3) | “bc” |
| boolean equals(Object obj) | 比較字符串內(nèi)容(區(qū)分大小寫(xiě)) | “abc”.equals(“ABC”) | false |
| boolean equalsIgnoreCase(String str) | 比較字符串內(nèi)容(忽略大小寫(xiě)) | “abc”.equalsIgnoreCase(“ABC”) | true |
| int indexOf(String str) | 查找子串首次出現(xiàn)的索引(無(wú)則返回 -1) | “abcabc”.indexOf(“bc”) | 1 |
| String replace(CharSequence old, CharSequence new) | 替換字符/字符串 | “abac”.replace(“a”, “x”) | “xbxc” |
| String[] split(String regex) | 按分隔符拆分字符串(regex 支持正則) | “a,b,c”.split(“,”) | [“a”,“b”,“c”] |
| boolean isEmpty() | 判斷字符串是否為空(長(zhǎng)度為 0) | “”.isEmpty() | true |
2. StringBuilder(可變、單線(xiàn)程首選)
專(zhuān)為單線(xiàn)程場(chǎng)景設(shè)計(jì),可變字符序列,所有操作都在同一個(gè)對(duì)象上完成,無(wú)額外內(nèi)存開(kāi)銷(xiāo),是日常字符串拼接的最優(yōu)選擇。
(1)核心構(gòu)造方法
| 構(gòu)造方法 | 說(shuō)明 | 示例 |
|---|---|---|
| StringBuilder() | 創(chuàng)建空對(duì)象,初始容量 16 | StringBuilder sb = new StringBuilder(); |
| StringBuilder(int capacity) | 指定初始容量(減少擴(kuò)容開(kāi)銷(xiāo),推薦) | StringBuilder sb = new StringBuilder(32); |
| StringBuilder(CharSequence seq) | 通過(guò)字符串/字符序列初始化 | StringBuilder sb = new StringBuilder(“hello”); |
(2)常用方法(必須掌握)
注:方法均返回自身對(duì)象,支持鏈?zhǔn)秸{(diào)用。
| 方法名 | 說(shuō)明 | 示例(基于 sb = new StringBuilder(“abc”)) | 操作后 sb 內(nèi)容 |
|---|---|---|---|
| StringBuilder append(任意類(lèi)型) | 拼接內(nèi)容(支持字符串、數(shù)字、對(duì)象等) | sb.append(123).append(“def”) | “abc123def” |
| String toString() | 轉(zhuǎn)換為最終的 String 對(duì)象(必調(diào)方法) | sb.toString() | “abc123def” |
| StringBuilder delete(int start, int end) | 刪除指定區(qū)間字符(左閉右開(kāi)) | sb.delete(1,3) | “a123def” |
| StringBuilder insert(int offset, 任意類(lèi)型) | 在指定位置插入內(nèi)容 | sb.insert(3, “xyz”) | “abcxyz123def” |
| StringBuilder reverse() | 反轉(zhuǎn)字符串 | sb.reverse() | “fed321cba” |
| int capacity() | 獲取當(dāng)前容量(底層數(shù)組長(zhǎng)度) | sb.capacity() | 初始 16,擴(kuò)容后按 2*capacity+2 增長(zhǎng) |
| void setLength(int newLength) | 設(shè)置字符串長(zhǎng)度(短則截?cái)啵L(zhǎng)則補(bǔ) ‘\0’) | sb.setLength(5) | “abc12” |
3. StringBuffer(可變、多線(xiàn)程安全)
與 StringBuilder 功能完全一致,唯一區(qū)別是所有方法都加了 synchronized 關(guān)鍵字,保證多線(xiàn)程安全,但性能略低。
(1)核心構(gòu)造方法
與 StringBuilder 完全相同:
// 1. 空構(gòu)造,初始容量 16
StringBuffer sb = new StringBuffer();
// 2. 指定初始容量
StringBuffer sb = new StringBuffer(64);
// 3. 用字符串初始化
StringBuffer sb = new StringBuffer("hello");
(2)常用方法
與 StringBuilder 完全相同,僅多了線(xiàn)程安全特性。示例(多線(xiàn)程拼接):
StringBuffer sb = new StringBuffer();
// 多線(xiàn)程拼接不會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)亂
new Thread(() -> sb.append("a")).start();
new Thread(() -> sb.append("b")).start();
// 最終 sb 內(nèi)容為 "ab" 或 "ba",但長(zhǎng)度一定是 2(線(xiàn)程安全)
4. StringJoiner(JDK8+,分隔符拼接專(zhuān)用)
JDK8 引入的工具類(lèi),本質(zhì)是對(duì) StringBuilder 的封裝,專(zhuān)為「帶分隔符的字符串拼接」設(shè)計(jì),無(wú)需手動(dòng)處理“最后多一個(gè)分隔符”的問(wèn)題,語(yǔ)法更簡(jiǎn)潔。
(1)核心構(gòu)造方法
| 構(gòu)造方法 | 說(shuō)明 | 示例 |
|---|---|---|
| StringJoiner(CharSequence delimiter) | 僅指定分隔符 | StringJoiner joiner = new StringJoiner(“,”); |
| StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix) | 指定分隔符 + 前綴 + 后綴(常用) | StringJoiner joiner = new StringJoiner(“,”, “[”, “]”); |
(2)常用方法
注:方法返回自身,支持鏈?zhǔn)秸{(diào)用。
| 方法名 | 說(shuō)明 | 示例(基于 joiner = new StringJoiner(“,”, “[”, “]”)) | 操作后結(jié)果 |
|---|---|---|---|
| StringJoiner add(CharSequence newElement) | 添加拼接元素 | joiner.add(“Java”).add(“Python”).add(“Go”) | “[Java,Python,Go]” |
| String toString() | 轉(zhuǎn)換為最終 String 對(duì)象 | joiner.toString() | “[Java,Python,Go]” |
| StringJoiner merge(StringJoiner other) | 合并另一個(gè) StringJoiner(復(fù)用分隔符/前綴/后綴) | joiner.merge(new StringJoiner(“,”).add(“C++”)) | “[Java,Python,Go,C++]” |
| StringJoiner setEmptyValue(CharSequence emptyValue) | 設(shè)置空值時(shí)的默認(rèn)輸出(無(wú)元素時(shí)生效) | new StringJoiner(“,”).setEmptyValue(“空”).toString() | “空” |
三、實(shí)戰(zhàn)示例對(duì)比(直觀理解差異)
用四個(gè)類(lèi)分別實(shí)現(xiàn)「拼接 1-10 的數(shù)字為 “1,2,3,…,10”」,對(duì)比實(shí)現(xiàn)復(fù)雜度和性能:
import java.util.StringJoiner;
public class StringCompareDemo {
public static void main(String[] args) {
// 1. String(性能差,不推薦頻繁拼接)
String str = "";
for (int i = 1; i <= 10; i++) {
str += i + (i == 10 ? "" : ","); // 手動(dòng)處理分隔符,頻繁生成臨時(shí)對(duì)象
}
System.out.println("String: " + str); // 輸出:1,2,3,4,5,6,7,8,9,10
// 2. StringBuilder(單線(xiàn)程推薦,高性能)
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10; i++) {
sb.append(i);
if (i != 10) sb.append(","); // 手動(dòng)處理分隔符
}
System.out.println("StringBuilder: " + sb); // 輸出:1,2,3,4,5,6,7,8,9,10
// 3. StringBuffer(多線(xiàn)程用,單線(xiàn)程沒(méi)必要)
StringBuffer sbf = new StringBuffer();
for (int i = 1; i <= 10; i++) {
sbf.append(i).append(i == 10 ? "" : ",");
}
System.out.println("StringBuffer: " + sbf); // 輸出:1,2,3,4,5,6,7,8,9,10
// 4. StringJoiner(分隔符拼接最優(yōu),無(wú)需手動(dòng)處理分隔符)
StringJoiner joiner = new StringJoiner(",");
for (int i = 1; i <= 10; i++) {
joiner.add(String.valueOf(i)); // 直接添加,自動(dòng)處理分隔符
}
System.out.println("StringJoiner: " + joiner); // 輸出:1,2,3,4,5,6,7,8,9,10
}
}
四、總結(jié)(復(fù)習(xí)核心原則)
如果字符串無(wú)需修改(如常量、配置):用 String;
如果單線(xiàn)程環(huán)境下需要頻繁拼接/修改:用 StringBuilder(首選);
如果多線(xiàn)程環(huán)境下需要頻繁拼接/修改:用 StringBuffer;
如果需要拼接帶分隔符的字符串(如列表、數(shù)組轉(zhuǎn)字符串):用 StringJoiner(JDK8+)
到此這篇關(guān)于Java字符串四大類(lèi)之String、StringBuffer、StringBuilder、StringJoiner的文章就介紹到這了,更多相關(guān)Java字符串String、StringBuffer、StringBuilder、StringJoiner內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java字符處理之char、String、StringBuilder和StringBuffer詳解
- Java中的char、String、StringBuilder與StringBuffer全方面解析
- Java中String、StringBuffer和StringBuilder底層實(shí)現(xiàn)深入剖析
- Java中String、StringBuffer和StringBuilder的區(qū)別
- Java中StringBuilder與StringBuffer的區(qū)別
- Java中StringBuilder與StringBuffer使用及源碼解讀
- 淺析Java中StringBuffer和StringBuilder的使用
- 詳解Java中String,StringBuffer和StringBuilder的使用
- Java中String和StringBuffer及StringBuilder?有什么區(qū)別
- Java 中 String、StringBuffer、StringBuilder 的區(qū)別
相關(guān)文章
使用Spring掃描Mybatis的mapper接口的三種配置
這篇文章主要介紹了使用Spring掃描Mybatis的mapper接口的三種配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
Java 遞歸查詢(xún)部門(mén)樹(shù)形結(jié)構(gòu)數(shù)據(jù)的實(shí)踐
本文主要介紹了Java 遞歸查詢(xún)部門(mén)樹(shù)形結(jié)構(gòu)數(shù)據(jù)的實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Java設(shè)計(jì)模式之抽象工廠模式簡(jiǎn)析
這篇文章主要介紹了Java設(shè)計(jì)模式之抽象工廠模式簡(jiǎn)析, 抽象工廠模式是工廠方法模式的升級(jí)版本,他用來(lái)創(chuàng)建一組相關(guān)或者相互依賴(lài)的對(duì)象,他與工廠方法模式的區(qū)別就在于,工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu),需要的朋友可以參考下2023-12-12
java 刪除文件夾中的所有內(nèi)容而不刪除文件夾本身的實(shí)例
下面小編就為大家?guī)?lái)一篇java 刪除文件夾中的所有內(nèi)容而不刪除文件夾本身的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
使用SpringMVC返回json字符串的實(shí)例講解
下面小編就為大家分享一篇使用SpringMVC返回json字符串的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
詳解java中List中set方法和add方法的區(qū)別
本文主要介紹了詳解java中List中set方法和add方法的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
第三方網(wǎng)站微信登錄java代碼實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了第三方網(wǎng)站微信登錄的java代碼實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
HttpServletRequest對(duì)象方法的用法小結(jié)
HttpServletRequest對(duì)象代表客戶(hù)端的請(qǐng)求,當(dāng)客戶(hù)端通過(guò)HTTP協(xié)議訪問(wèn)服務(wù)器時(shí),HTTP請(qǐng)求頭中的所有信息都封裝在這個(gè)對(duì)象中,開(kāi)發(fā)人員通過(guò)這個(gè)對(duì)象的相關(guān)方法,即可以獲得客戶(hù)的這些信息2017-03-03

