淺談StringBuilder類的capacity()方法和length()方法的一些小坑
今天在做項(xiàng)目的過程中遇見一個(gè)StringBuilder.delete()刪除得不到自己期望結(jié)果問題,一個(gè)截取字符串的問題,總得不到自己所期望的答案:
問題如下:
stringBuilder.delete(stringBuilder.capacity() - 5, stringBuilder.capacity());
此句代碼要么報(bào)錯(cuò),要么多刪,要么少刪,也有時(shí)候正確。也有時(shí)候得不到自己所想要的字符串;
簡單的測試capacity()方法和length()方法的區(qū)別如下:
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abcdefgh2321");
System.out.println("length:" + stringBuilder.length());
System.out.println("capacity:" + stringBuilder.capacity());
System.out.println("length截?。? + stringBuilder.delete(stringBuilder.length() - 3,stringBuilder.length()));
System.out.println("capacity截取:" + stringBuilder.delete(stringBuilder.capacity() - 7,stringBuilder.capacity()));
System.out.println("capacity截?。? + stringBuilder.delete(stringBuilder.capacity() - 5,stringBuilder.capacity()));
代碼如上:
輸出:

最后查看源碼,
StringBuilder類繼承于AbstractStringBuilder抽象類:

在AbstractStringBuilder抽象類中,放入進(jìn)去的字符串存儲(chǔ)于char[] value 數(shù)組中,count為存進(jìn)去的字符數(shù)目,
使用capacity()方法得到的為 value數(shù)組的長度,length()方法得到的為count,也就是字符串的實(shí)際長度。


在初始化StringBuilder時(shí)候,也就是new StringBuilder()時(shí)候,會(huì)初始化一個(gè)char[16]大小的char數(shù)據(jù)來存儲(chǔ)字符串,如果字符串增加之后,會(huì)進(jìn)行擴(kuò)容。


當(dāng)然,如果 new StringBuilder("213123");會(huì)在字符串的長度的增加16作為初始數(shù)組char[] value的大小,

最后:
希望大家在使用capacity()方法和length()方法時(shí)要注意選擇:否則會(huì)導(dǎo)致意想不到的坑。
StringBuilder初始化的大小對性能的影響
StringBuilder 是一個(gè)可以動(dòng)態(tài)增加自身數(shù)據(jù)長度的類,其默認(rèn)長度(capacity屬性)為16。
它有一個(gè)構(gòu)造函數(shù),可以指定其容器長度。當(dāng)數(shù)據(jù)量小時(shí),指定長度意義不大,但是當(dāng)數(shù)據(jù)量比較大時(shí),指定長度會(huì)對性能產(chǎn)生顯著影響。
本文通過一個(gè)小示例驗(yàn)證其對性能產(chǎn)生的影響
代碼如下:
public class StringBuilderTest {
public static void main(String[] args) throws Exception {
// 前兩行分別是獲取運(yùn)行次數(shù)和StringBuilder的初始化長度
int times = args.length > 0 ? Integer.parseInt(args[0]) : 100;
int length = args.length > 1 ? Integer.parseInt(args[1]) : 0;
// 運(yùn)行 times 次的 test(length)方法
long t1 = System.currentTimeMillis();
for (int i = 0; i < times; i++)
test(length);
long t2 = System.currentTimeMillis();
// 輸出單次運(yùn)行時(shí)間
System.out.printf("Time taken: %d ms.\n", (t2 - t1) / times);
}
// 這個(gè)方法只是單純地做循環(huán)向StringBuilder中添加數(shù)據(jù)。
static int test(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < 10000000; i++)
sb.append(i + "");
return sb.length();
}
}
以下是編碼后,分配2GB內(nèi)存,在控制臺(tái)測試運(yùn)行100次的運(yùn)行結(jié)果。
$ java -Xmx2g -Xms2g StringBuilderTest 100 0
Time taken: 273 ms.
$ java -Xmx2g -Xms2g StringBuilderTest 100 73000000
Time taken: 205 ms.
性能差距約為30%
結(jié)論
當(dāng)在使用StringBuilder處理大數(shù)據(jù)的時(shí)候,如果我們可以預(yù)知或者以很小的性能損失就能獲得數(shù)據(jù)的大小時(shí),提前指定StringBuilder的長度可顯著提高處理速度。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用chatgpt實(shí)現(xiàn)微信聊天小程序的代碼示例
這篇文章主要介紹了使用chatgpt實(shí)現(xiàn)微信聊天小程序(秒回復(fù)),文中有詳細(xì)的代碼示例,對大家了解chatgpt聊天有一定的幫助,感興趣的同學(xué)可以參考閱讀2023-05-05
Java的MyBatis框架中關(guān)鍵的XML字段映射的配置參數(shù)詳解
將XML文件的schema字段映射到數(shù)據(jù)庫的schema是我們操作數(shù)據(jù)庫的常用手段,這里我們就來整理一些Java的MyBatis框架中關(guān)鍵的XML字段映射的配置參數(shù)詳解,需要的朋友可以參考下2016-06-06
Java中的SynchronousQueue阻塞隊(duì)列及使用場景解析
這篇文章主要介紹了Java中的SynchronousQueue阻塞隊(duì)列及使用場景解析,SynchronousQueue 是 Java 中的一個(gè)特殊的阻塞隊(duì)列,它的主要特點(diǎn)是它的容量為0,這意味著 SynchronousQueue不會(huì)存儲(chǔ)任何元素,需要的朋友可以參考下2023-12-12
Java實(shí)現(xiàn)獲取圖片和視頻文件的Exif信息
這篇文章將重點(diǎn)為大家介紹一下如何使用Java編程語言結(jié)合metadata-extractor去自動(dòng)獲取全景圖片的Exif信息,獲取照片的拍攝坐標(biāo)信息,感興趣的可以了解一下2022-11-11
mybatis的insert插入后獲取自增id的方法詳解(從controller到mapper)
這篇文章主要介紹了mybatis的insert插入后獲取自增id的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-10-10
POI導(dǎo)出之Excel實(shí)現(xiàn)單元格的背景色填充問題
這篇文章主要介紹了POI導(dǎo)出之Excel實(shí)現(xiàn)單元格的背景色填充問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

