淺談StringBuilder類的capacity()方法和length()方法的一些小坑
今天在做項目的過程中遇見一個StringBuilder.delete()刪除得不到自己期望結(jié)果問題,一個截取字符串的問題,總得不到自己所期望的答案:
問題如下:
stringBuilder.delete(stringBuilder.capacity() - 5, stringBuilder.capacity());
此句代碼要么報錯,要么多刪,要么少刪,也有時候正確。也有時候得不到自己所想要的字符串;
簡單的測試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)去的字符串存儲于char[] value 數(shù)組中,count為存進(jìn)去的字符數(shù)目,
使用capacity()方法得到的為 value數(shù)組的長度,length()方法得到的為count,也就是字符串的實際長度。


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


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

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

