2015-03-25 80 views
4

我看到了四種替代方法,用於將char轉換爲Java中的StirngJava中最快的字符串轉換

v = Something.lookup(new String((char)binaryData[idx])); // SORRY! Wrong. 
v = Something.lookup("" + (char)binaryData[idx]); 
v = Something.lookup(String.valueOf((char)binaryData[idx])); 
v = Something.lookup(Character.toString((char)binaryData[idx]))); 

我認爲第一個是最慢的。第二個非常方便。我推測第三個可能會返回以前創建的String實例,但我不確定,API文檔沒有這樣說。選項四也是如此。實例的重用將非常幸運,因爲然後基於散列的查找可以利用String中的hashCode()高速緩存。 (哪些功能在API文檔中也沒有描述,但很多人告訴我)。

我來自C++,我覺得缺乏複雜性信息令人不安。 :-)我的猜測是否正確?我們是否有任何形式的官方文檔,在其中聲明瞭性能保證和緩存機制?

+5

「第二個非常方便」 - 不是如果你想讀代碼,國際海事組織。該代碼使用字符串連接和一個空字符串,這兩者都不是你真正想實現的一部分。 'String.valueOf'一路,海事組織 - 並且你*測量了*這些中的任何一個?你知道嗎,這實際上是代碼中的瓶頸?你有沒有嘗試確定'String.valueof' *是否緩存這些值? (很容易分辨......)假設'binaryData'是一個'byte []',你可以很容易地用256個字符串構建你自己的'String []',以絕對保證緩存...... – 2015-03-25 10:28:40

+0

3和4同樣的..暗含地調用3 :)。我們還沒有一個String構造函數,它只接受一個字符(case-1?) – TheLostMind 2015-03-25 10:30:58

+0

版本2將由編譯器翻譯爲:創建一個StringBuilder對象,然後將char添加到該對象,最後toString()將被調用。所以這相當昂貴。對於v3或v4的成本...你可以看看源代碼,看看會發生什麼。 – GhostCat 2015-03-25 10:32:12

回答

6

首先,Java規範不說有關性能什麼關於這四種方法,因此結果可能會有所不同,具體取決於您使用的JRE版本和供應商。

如果您使用Oracle的JRE,您可以輕鬆地自行檢查源代碼!在Java 8中,如下所示:

鑑於一些價值char c

  • new String(c)不能編譯。沒有這樣的構造函數。
  • "" + c看起來醜陋,麻煩和棘手。它在內部創建一個新的空字段StringBuilder並將字符附加到它。然後它會從StringBuilder中創建一個新的String實例。
  • Character.toString(c)代表String.valueOf(c)
  • String.valueOf(c)創建一個新的String實例。

那麼,哪一個使用?

最易讀!

這就是我的觀點String.valueOf(c)Character.toString(c)

+0

你是對的! ;)謝謝,我已經解決了我的答案。 – isnot2bad 2015-03-25 11:06:07

+1

你很想討論字符串實習生,以便讓答案更完整。我敢打賭,所有低於256的acii字符都是在啓動時被實施(緩存)的。 – 2015-03-25 11:36:14

+1

由於在HotSpot JVM中進行了特殊的優化,''「+ c'會稍微快一點,但爲了便於閱讀,我也更喜歡'Character.toString'或'String.valueOf'。 – apangin 2015-03-25 11:40:09

2

第二個肯定是(在理論上)慢,因爲它被翻譯成

v = Something.lookup(new StringBuilder().append("").append((char)binaryData[idx]).toString()); 

StringBuilder S使用初始化的char[]持有16個值被實現。因此,StringBuilder選項會初始化一個大小爲16的char[],僅用於將設置的單元格(此例中僅爲第一個)複製到結果字符串中。

String.valueOf(其等同於Character.toString)使用尺寸1的char[],然後直接設置String的背襯char[],從而避免了複製的需要。

第一種方法不會編譯(至少是沒有的Java 7),因爲沒有String構造函數接受單個字符作爲輸入:http://docs.oracle.com/javase/7/docs/api/java/lang/String.html

+2

「*第二個肯定比較慢*」==>你會感到驚訝...... – assylias 2015-03-25 10:50:56

+0

我的意思是說第二個選項可以做更多的工作,理論上應該更慢。 – EvenLisle 2015-03-25 10:54:00

+0

*理論上理論和實踐之間沒有區別,實際上存在。*「:-)它發生在三個選項與Hotspot JVM 8之間沒有明顯的區別。 – assylias 2015-03-25 11:15:30

1

第一個解決方案不能編譯。 第二種解決方案在內部創建一個字符串,調用類似於Character.valueOf(char)的代碼。 解決方案三比第四更好,因爲內部實現Character.toString(char ch)String.valueOf

public static String toString(char c) { 
    return String.valueOf(c); 
} 

內部執行第三String.valueOf(char ch)的呼叫

public static String valueOf(char c) { 
    char data[] = {c}; 
    return new String(0, 1, data); 
} 
1

我是從C++來了,我覺得這缺乏複雜的信息令人不安。 :-)我的猜測是否正確?我們是否有任何形式的官方文檔,在其中聲明瞭性能保證和緩存機制?

回答這個問題的部分:一般來說沒有。您會發現內置集合的漸近性能以及其他幾個方面的信息,但總的來說,這些問題留給VM實施者自行決定。您當然可以始終查看源代碼,但請記住,有些事情會影響您無法直接控制的性能:JIT編譯和垃圾回收是兩個最大的問題。

你應該爲此感到不安嗎?我不這麼認爲,Java運行的前提是低級性能很少是應用程序開發人員需要關注的問題。這是一種折衷,你可以爭論這是否是一個好的折衷,但它就是這樣。

但是到了開發真正高性能系統的時候,您將一路領略所有必要的信息。

+0

如果可以的話,我會添加更多的提示,因爲這是處理問題第二部分的唯一答案。 – Notinlist 2015-03-25 12:44:35

+1

@Notinlist只是一個小小的附錄:你的問題(或者說,你得到的答案)表明了這種在實踐中很少實施保證的政策。 ''「」+ c「開始是一種」壞習慣「,這是非常令人不悅的,而且確實很慢。但是從Java 8開始,這種模式顯然被JIT編譯器所認可,它可以像所有其他解決方案一樣快速地生成代碼。如果對實施細節有更多保證,也許這是不可能的。 – biziclop 2015-03-25 13:10:26