最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從內(nèi)存方面解釋Java中String與StringBuilder的性能差異

 更新時(shí)間:2016年05月18日 16:08:44   作者:CodePlayer  
我們通常會(huì)發(fā)現(xiàn)使用StringBuffer或StringBuilder創(chuàng)建出來(lái)的字符串在拼接時(shí)回避String要來(lái)得快,尤其是StringBuilder,本文就從內(nèi)存方面解釋Java中String與StringBuilder的性能差異,需要的朋友可以參考下

以前經(jīng)常在網(wǎng)上看到關(guān)于Java字符串拼接等方面的討論。看到有些Java開(kāi)發(fā)人員在給新手程序員的建議中類(lèi)似如下寫(xiě)道:

不要使用+號(hào)拼接字符串,要使用StringBuffer或StringBuilder的append()方法來(lái)拼接字符串。
不過(guò),用+號(hào)拼接字符串就真的那么令人討厭,難道使用+號(hào)拼接字符串就沒(méi)有一點(diǎn)可取之處嗎?

通過(guò)查閱Java API文檔中關(guān)于String類(lèi)的部分內(nèi)容,我們可以看到如下片段:
“Java 語(yǔ)言提供對(duì)字符串串聯(lián)符號(hào)("+")以及將其他對(duì)象轉(zhuǎn)換為字符串的特殊支持。字符串串聯(lián)是通過(guò) StringBuilder(或 StringBuffer)類(lèi)及其 append 方法實(shí)現(xiàn)的。字符串轉(zhuǎn)換是通過(guò) toString 方法實(shí)現(xiàn)的,該方法由 Object 類(lèi)定義,并可被 Java中的所有類(lèi)繼承?!?/p>

這段話(huà)很明確地告訴我們,在Java中使用+號(hào)拼接字符串,實(shí)際上使用的就是StringBuffer或StringBuilder及其append方法來(lái)實(shí)現(xiàn)的。

除了Java API文檔,我們還可以使用工具查看class類(lèi)文件的字節(jié)碼命令來(lái)得到上述答案。 例如代碼:

public static void main(String[] args) {
  String a = "Hello";
  String b = " world";
  String str = a + b + " !";
  System.out.println(str);
}

通過(guò)工具查看到其對(duì)應(yīng)的字節(jié)碼命令如下:

2016518160343602.jpg (939×352)

從字節(jié)碼命令中,我們可以清楚地看到,我們編寫(xiě)的如下代碼

String str = a + b + " !";

被編譯器轉(zhuǎn)換成了類(lèi)似如下語(yǔ)句:

String str = new StringBuilder(String.valueOf(a)).append(b).append(" !").toString();

不僅如此,Java的編譯器也是一個(gè)比較聰明的編譯器,當(dāng)+號(hào)拼接的全部是字符串字面量時(shí),Java的編譯器將會(huì)在編譯時(shí)智能地將其轉(zhuǎn)換為一個(gè)完整的字符串。例如:

public static void main(String[] args) {
  String str = "Hello" + " world" + ", Java!";
  System.out.println(str);
}

Java編譯器直接將這種全是字面量的字符串拼接,在編譯時(shí)就轉(zhuǎn)換為了一個(gè)完整的字符串。

2016518160430161.jpg (707×145)

就算+號(hào)拼接的字符串中存在變量,Java編譯器也會(huì)將最前面的字符串字面量合并為一個(gè)字符串。

public static void main(String[] args) {
  String java = ", Java!";
  String str = "Hello" + " world" + java;
  System.out.println(str);
}

2016518160449064.jpg (935×265)

從上述可知,對(duì)于類(lèi)似String str = str1 + str2 + str3 + str4,這種將多個(gè)字符串一次性拼接的操作,使用+號(hào)來(lái)進(jìn)行拼接是完全沒(méi)有問(wèn)題的。

在Java中,String對(duì)象是不可變的(Immutable)。在代碼中,可以創(chuàng)建多個(gè)某一個(gè)String對(duì)象的別名。但是這些別名都是的引用是相同的。
比如s1和s2都是”droidyue.com”對(duì)象的別名,別名保存著到真實(shí)對(duì)象的引用。所以s1 = s2

String s1 = "droidyue.com";
String s2 = s1;
System.out.println("s1 and s2 has the same reference =" + (s1 == s2));

并且在Java中,唯一被重載的運(yùn)算符就是字符串的拼接相關(guān)的。+,+=。除此之外,Java設(shè)計(jì)者不允許重載其他的運(yùn)算符。

在Java中,唯一被重載的運(yùn)算符就是字符串的拼接相關(guān)的。+,+=。除此之外,Java設(shè)計(jì)者不允許重載其他的運(yùn)算符。

眾所周知,在Java 1.4版本之前,字符串拼接可以使用StringBuffer,從Java 1.5開(kāi)始,我們可以使用StringBuilder來(lái)拼接字符串。StringBuffer和StringBuilder的主要區(qū)別在于:StringBuffer是線程安全的,適用于多線程操作字符串;StringBuilder是線程不安全的,適合單線程下操作字符串。不過(guò),我們的大多數(shù)字符串拼接操作都是在單線程下進(jìn)行的,因此使用StringBuilder有利于提高性能。

在Java 1.4之前,編譯器使用StringBuffer來(lái)處理+號(hào)拼接的字符串;從Java 1.5開(kāi)始,編譯器大多數(shù)情況下都使用StringBuilder來(lái)處理+號(hào)拼接的字符串。

當(dāng)我們?cè)贘DK 1.4的環(huán)境下編寫(xiě)代碼時(shí),對(duì)于上述這種一次性拼接多個(gè)字符串的情況,建議最好使用+號(hào)來(lái)處理。這樣,當(dāng)JDK 升級(jí)到1.5及以上版本時(shí),編譯器將會(huì)自動(dòng)將其轉(zhuǎn)換為StringBuilder來(lái)拼接字符串,從而提高字符串拼接效率。

當(dāng)然,推薦使用+號(hào)拼接字符串也僅限于在一條語(yǔ)句中拼接多個(gè)字符串時(shí)使用。如果分散在多條語(yǔ)句中拼接一個(gè)字符串,仍然建議使用StringBuffer或StringBuilder。 例如:

public static void main(String[] args) {
  String java = ", Java!";
  String str = "";
  str += "Hello";
  str += " world";
  str += java;
  System.out.println(str);
}

編譯器編譯后的字節(jié)命令如下:

2016518160507152.jpg (945×603)

從上面的圖片中我們可以知道,每一條+號(hào)拼接語(yǔ)句,都創(chuàng)建了一個(gè)新的StringBuilder對(duì)象。這種情況在循環(huán)條件下表現(xiàn)得尤其明顯,造成了相對(duì)較大的性能損耗。因此,在多條語(yǔ)句中拼接字符串,強(qiáng)烈建議使用StringBuffer或StringBuilder來(lái)處理。

關(guān)于使用StringBuilder帶來(lái)的優(yōu)化

此外,在使用StringBuffer或StringBuilder的時(shí)候,我們還可以使用如下方式,進(jìn)一步提高性能(下面代碼以StringBuilder為例,StringBuffer與此類(lèi)似)。

1.預(yù)測(cè)最終獲得的字符串的最大長(zhǎng)度。

StringBuilder內(nèi)部char數(shù)組的默認(rèn)長(zhǎng)度為16,當(dāng)我們append追加字符串后超過(guò)此長(zhǎng)度時(shí),StringBuilder會(huì)擴(kuò)大內(nèi)部的數(shù)組容量以滿(mǎn)足需要。在這個(gè)過(guò)程中,StringBuilder會(huì)創(chuàng)建一個(gè)新的較大容量的char數(shù)組,并將原數(shù)組中的數(shù)據(jù)復(fù)制到新數(shù)組中。如果我們能夠大致預(yù)測(cè)到最終拼接得到的字符串的最大長(zhǎng)度,就可以在創(chuàng)建StringBuilder對(duì)象時(shí)指定合適大小的初始容量。例如,我們需要拼接獲得含有100個(gè)字母a的字符串。即可編寫(xiě)如下代碼:

StringBuilder sb = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
  sb.append('a');
}
System.out.println(sb);

請(qǐng)根據(jù)實(shí)際情況進(jìn)行平衡,以創(chuàng)建適合初始容量的StringBuilder。

2.對(duì)于單個(gè)字符,盡可能地使用char類(lèi)型,而不是String類(lèi)型。

有些時(shí)候,我們需要在字符串后追加單個(gè)字符(例如:a),此時(shí)應(yīng)盡可能地使用

sb.append('a');

而不是使用:

sb.append("a");

相關(guān)文章

  • SpringMVC?Restful風(fēng)格與中文亂碼問(wèn)題解決方案介紹

    SpringMVC?Restful風(fēng)格與中文亂碼問(wèn)題解決方案介紹

    Restful就是一個(gè)資源定位及資源操作的風(fēng)格,不是標(biāo)準(zhǔn)也不是協(xié)議,只是一種風(fēng)格,是對(duì)http協(xié)議的詮釋,下面這篇文章主要給大家介紹了關(guān)于SpringMVC對(duì)Restful風(fēng)格支持的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • 關(guān)于Redis的緩存穿透問(wèn)題

    關(guān)于Redis的緩存穿透問(wèn)題

    這篇文章主要介紹了關(guān)于Redis的緩存穿透問(wèn)題,緩存穿透是指客戶(hù)端請(qǐng)求的數(shù)據(jù)在緩存中和數(shù)據(jù)庫(kù)中都不存在,這樣緩存永遠(yuǎn)不會(huì)生效,這些請(qǐng)求都會(huì)打到數(shù)據(jù)庫(kù),需要的朋友可以參考下
    2023-08-08
  • Springboot自動(dòng)加載配置的原理解析

    Springboot自動(dòng)加載配置的原理解析

    Springboot遵循“約定優(yōu)于配置”的原則,使用注解對(duì)一些常規(guī)的配置項(xiàng)做默認(rèn)配置,減少或不使用xml配置,讓你的項(xiàng)目快速運(yùn)行起來(lái),這篇文章主要給大家介紹了關(guān)于Springboot自動(dòng)加載配置原理的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • spring-retry組件的使用教程

    spring-retry組件的使用教程

    Spring Retry的主要目的是為了提高系統(tǒng)的可靠性和容錯(cuò)性,當(dāng)方法調(diào)用失敗時(shí),Spring Retry可以在不影響系統(tǒng)性能的情況下,自動(dòng)進(jìn)行重試,從而減少故障對(duì)系統(tǒng)的影響,這篇文章主要介紹了spring-retry組件的使用,需要的朋友可以參考下
    2023-06-06
  • Java實(shí)現(xiàn)簡(jiǎn)易學(xué)籍管理系統(tǒng)

    Java實(shí)現(xiàn)簡(jiǎn)易學(xué)籍管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)易學(xué)籍管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 如何優(yōu)雅的進(jìn)行Spring整合MongoDB詳解

    如何優(yōu)雅的進(jìn)行Spring整合MongoDB詳解

    這篇文章主要給大家介紹了如何優(yōu)雅的進(jìn)行Spring整合MongoDB的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-02-02
  • Spring集成Quartz的簡(jiǎn)單配置的方法

    Spring集成Quartz的簡(jiǎn)單配置的方法

    本篇文章主要介紹了Spring集成Quartz的簡(jiǎn)單配置的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • java操作mongodb示例分享

    java操作mongodb示例分享

    這篇文章主要介紹了java操作mongodb示例,實(shí)現(xiàn)了簡(jiǎn)單的條件查詢(xún)和復(fù)雜的條件查詢(xún),需要的朋友可以參考下
    2014-02-02
  • Mybatis在sqlite中無(wú)法讀寫(xiě)byte[]類(lèi)問(wèn)題的解決辦法

    Mybatis在sqlite中無(wú)法讀寫(xiě)byte[]類(lèi)問(wèn)題的解決辦法

    這篇文章主要給大家介紹了關(guān)于Mybatis在sqlite中無(wú)法讀寫(xiě)byte[]類(lèi)問(wèn)題的解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • java request.getHeader(

    java request.getHeader("user-agent")獲取瀏覽器信息的方法

    這篇文章主要介紹了java request.getHeader("user-agent")獲取瀏覽器信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03

最新評(píng)論

卫辉市| 瑞昌市| 山西省| 锡林浩特市| 海晏县| 明溪县| 安岳县| 江口县| 清水县| 精河县| 页游| 锦州市| 朔州市| 宁波市| 布尔津县| 枣强县| 昭苏县| 宁陵县| 内丘县| 克拉玛依市| 珠海市| 藁城市| 礼泉县| 溆浦县| 金塔县| 汝州市| 永善县| 温州市| 汝州市| 晴隆县| 高邮市| 德江县| 潞城市| 黑河市| 大悟县| 九龙城区| 云梦县| 沙坪坝区| 西乌珠穆沁旗| 阿图什市| 麦盖提县|