淺談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抽象類中,放入進去的字符串存儲于char[] value 數(shù)組中,count為存進去的字符數(shù)目,
使用capacity()方法得到的為 value數(shù)組的長度,length()方法得到的為count,也就是字符串的實際長度。
在初始化StringBuilder時候,也就是new StringBuilder()時候,會初始化一個char[16]大小的char數(shù)據(jù)來存儲字符串,如果字符串增加之后,會進行擴容。
當(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)文章
SpringBoot基于RabbitMQ實現(xiàn)消息延遲隊列方案及使用場景
在很多的業(yè)務(wù)場景中,延時隊列可以實現(xiàn)很多功能,此類業(yè)務(wù)中,一般上是非實時的,需要延遲處理的,需要進行重試補償?shù)?這篇文章主要介紹了SpringBoot基于RabbitMQ實現(xiàn)消息延遲隊列方案及使用場景,需要的朋友可以參考下2024-04-04java基本教程之Thread中start()和run()的區(qū)別 java多線程教程
這篇文章主要介紹了Thread中start()和run()的區(qū)別,Thread類包含start()和run()方法,它們的區(qū)別是什么?下面將對此作出解答2014-01-01Spring RedirectAttributes參數(shù)跳轉(zhuǎn)代碼實例
這篇文章主要介紹了Spring RedirectAttributes參數(shù)跳轉(zhuǎn)代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-04-04Java?Spring?AOP源碼解析之事務(wù)實現(xiàn)原理
這篇文章主要為大家介紹了Java?Spring?AOP事務(wù)實現(xiàn)原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01詳解JUC并發(fā)編程中的進程與線程學(xué)習(xí)
這篇文章主要為大家詳細(xì)介紹了JUC并發(fā)編程中的進程與線程學(xué)習(xí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03Java創(chuàng)建student類詳細(xì)代碼例子
這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建student類的相關(guān)資料,學(xué)生類(Student)是一種面向?qū)ο蟮木幊谈拍?其主要用于描述學(xué)生的屬性和行為,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11