淺談StringBuilder類(lèi)的capacity()方法和length()方法的一些小坑
今天在做項(xiàng)目的過(guò)程中遇見(jiàn)一個(gè)StringBuilder.delete()刪除得不到自己期望結(jié)果問(wèn)題,一個(gè)截取字符串的問(wèn)題,總得不到自己所期望的答案:
問(wèn)題如下:
stringBuilder.delete(stringBuilder.capacity() - 5, stringBuilder.capacity());
此句代碼要么報(bào)錯(cuò),要么多刪,要么少刪,也有時(shí)候正確。也有時(shí)候得不到自己所想要的字符串;
簡(jiǎn)單的測(cè)試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類(lèi)繼承于AbstractStringBuilder抽象類(lèi):
在AbstractStringBuilder抽象類(lèi)中,放入進(jìn)去的字符串存儲(chǔ)于char[] value 數(shù)組中,count為存進(jìn)去的字符數(shù)目,
使用capacity()方法得到的為 value數(shù)組的長(zhǎng)度,length()方法得到的為count,也就是字符串的實(shí)際長(zhǎng)度。
在初始化StringBuilder時(shí)候,也就是new StringBuilder()時(shí)候,會(huì)初始化一個(gè)char[16]大小的char數(shù)據(jù)來(lái)存儲(chǔ)字符串,如果字符串增加之后,會(huì)進(jìn)行擴(kuò)容。
當(dāng)然,如果 new StringBuilder("213123");會(huì)在字符串的長(zhǎng)度的增加16作為初始數(shù)組char[] value的大小,
最后:
希望大家在使用capacity()方法和length()方法時(shí)要注意選擇:否則會(huì)導(dǎo)致意想不到的坑。
StringBuilder初始化的大小對(duì)性能的影響
StringBuilder 是一個(gè)可以動(dòng)態(tài)增加自身數(shù)據(jù)長(zhǎng)度的類(lèi),其默認(rèn)長(zhǎng)度(capacity屬性)為16。
它有一個(gè)構(gòu)造函數(shù),可以指定其容器長(zhǎng)度。當(dāng)數(shù)據(jù)量小時(shí),指定長(zhǎng)度意義不大,但是當(dāng)數(shù)據(jù)量比較大時(shí),指定長(zhǎng)度會(huì)對(duì)性能產(chǎn)生顯著影響。
本文通過(guò)一個(gè)小示例驗(yàn)證其對(duì)性能產(chǎn)生的影響
代碼如下:
public class StringBuilderTest { public static void main(String[] args) throws Exception { // 前兩行分別是獲取運(yùn)行次數(shù)和StringBuilder的初始化長(zhǎng)度 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)測(cè)試運(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的長(zhǎng)度可顯著提高處理速度。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何基于FTP4J實(shí)現(xiàn)FTPS連接過(guò)程解析
這篇文章主要介紹了如何基于FTP4J實(shí)現(xiàn)FTPS連接過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Java基礎(chǔ)之Thymeleaf的簡(jiǎn)單使用
這篇文章主要介紹了Java基礎(chǔ)之Thymeleaf的簡(jiǎn)單使用,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04SpringBoot基于RabbitMQ實(shí)現(xiàn)消息延遲隊(duì)列方案及使用場(chǎng)景
在很多的業(yè)務(wù)場(chǎng)景中,延時(shí)隊(duì)列可以實(shí)現(xiàn)很多功能,此類(lèi)業(yè)務(wù)中,一般上是非實(shí)時(shí)的,需要延遲處理的,需要進(jìn)行重試補(bǔ)償?shù)?這篇文章主要介紹了SpringBoot基于RabbitMQ實(shí)現(xiàn)消息延遲隊(duì)列方案及使用場(chǎng)景,需要的朋友可以參考下2024-04-04java基本教程之Thread中start()和run()的區(qū)別 java多線(xiàn)程教程
這篇文章主要介紹了Thread中start()和run()的區(qū)別,Thread類(lèi)包含start()和run()方法,它們的區(qū)別是什么?下面將對(duì)此作出解答2014-01-01Spring RedirectAttributes參數(shù)跳轉(zhuǎn)代碼實(shí)例
這篇文章主要介紹了Spring RedirectAttributes參數(shù)跳轉(zhuǎn)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Java?Spring?AOP源碼解析之事務(wù)實(shí)現(xiàn)原理
這篇文章主要為大家介紹了Java?Spring?AOP事務(wù)實(shí)現(xiàn)原理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-01-01詳解JUC并發(fā)編程中的進(jìn)程與線(xiàn)程學(xué)習(xí)
這篇文章主要為大家詳細(xì)介紹了JUC并發(fā)編程中的進(jìn)程與線(xiàn)程學(xué)習(xí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03Java創(chuàng)建student類(lèi)詳細(xì)代碼例子
這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建student類(lèi)的相關(guān)資料,學(xué)生類(lèi)(Student)是一種面向?qū)ο蟮木幊谈拍?其主要用于描述學(xué)生的屬性和行為,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11