2010-03-15 1604 views
9

我試圖將字符串的第一個字母轉換爲小寫。用Java替換String中的第一個字母?

value.substring(0,1).toLowerCase() + value.substring(1) 

這有效,但有沒有更好的方法來做到這一點?

我可以使用替換函數,但Java的替換不接受索引。你必須傳遞實際的字符/子字符串。它可以做這樣的:

value.replaceFirst(value.charAt(0), value.charAt(0).toLowerCase()) 

除了replaceFirst預計2個字符串,所以value.charAt(0)小號可能會需要與value.substring(0,1)更換。

是否有任何標準的方法來替換字符串的第一個字母?

+1

檢查StringUtils的:http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/StringUtils.html – Trick 2010-03-15 13:36:49

回答

12

我建議你看看Apache的Commons-Lang庫。他們有一個類

StringUtils 

它允許你用字符串做很多任務。在你的情況下,只需使用

StringUtils.uncapitalize(value) 

read here about uncapitalize以及關於類的其他功能建議

補充:我的經驗告訴Coomon郎是相當不錯的優化,所以如果想知道什麼是從算法的角度來看更好,你可以看看Apache的源代碼。

+0

除非它使用了'字符.toLowerCase'(http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/StringUtils.java?view=markup),這不是一個好主意(特別是在Java文檔中反推薦),因爲它不能正確處理區域設置或Unicode。有關詳細信息,請參閱我的評論(jambjo最初指出這一點,但刪除了答案)Marcus'答案的詳細信息:http://stackoverflow.com/questions/2447427/whats-the-best-way-to-replace-the-first字母順序在java中/ 2447655#2447655 – 2010-03-15 14:18:33

+0

然後我會說使用Character.toLowerCase或String#toLowerCase取決於情況。如果您確定Character.toLowerCase不會在您的案例中導致問題 - >使用它,因爲它的性能應該更好。這取決於;-) – Maxym 2010-03-15 14:31:33

+0

不夠公平,但我懷疑是否會有足夠的性能增益讓它值得設置維護問題(如今天的應用處理很多地區和Unicode內容)。 :-) – 2010-03-15 14:53:00

3

您使用的代碼(我在類似情況下使用過)的缺點是它看起來有點笨重,理論上至少會生成兩個立即丟棄的臨時字符串。如果您的字符串少於兩個字符,也會出現問題。

好處在於,您不會在表達式之外引用這些臨時字符串(讓字節碼編譯器或JIT優化程序將其打開以優化),並且您的意圖對於任何未來的代碼維護者都是明確的。

除非你需要做幾百萬次這些任何給定的第二個檢測這樣做的顯着性能問題,我不會擔心性能,並希望清晰。我也會把它埋在某個地方的實用課程中。 :-)另見jambjo對另一個答案的迴應,指出String#toLowerCaseCharacter.toLowerCase之間有一個重要的區別。 (編輯:答案,因此評論已被刪除基本上,有相關的語言環境和Unicode和文檔有很大的不同建議使用String#toLowerCase,不Character.toLowerCase; more here。)

編輯因爲我在一個奇怪的心情,我想我會看看在一個簡單的測試中是否有可測量的性能差異。有。這可能是因爲語言環境差(例如,蘋果與橘子)的:

public class Uncap 
{ 
    public static final void main(String[] params) 
    { 
     String s; 
     String s2; 
     long start; 
     long end; 
     int  counter; 

     // Warm up 
     s = "Testing"; 
     start = System.currentTimeMillis(); 
     for (counter = 1000000; counter > 0; --counter) 
     { 
      s2 = uncap1(s); 
      s2 = uncap2(s); 
      s2 = uncap3(s); 
     } 

     // Test v2 
     start = System.currentTimeMillis(); 
     for (counter = 1000000; counter > 0; --counter) 
     { 
      s2 = uncap2(s); 
     } 
     end = System.currentTimeMillis(); 
     System.out.println("2: " + (end - start)); 

     // Test v1 
     start = System.currentTimeMillis(); 
     for (counter = 1000000; counter > 0; --counter) 
     { 
      s2 = uncap1(s); 
     } 
     end = System.currentTimeMillis(); 
     System.out.println("1: " + (end - start)); 

     // Test v3 
     start = System.currentTimeMillis(); 
     for (counter = 1000000; counter > 0; --counter) 
     { 
      s2 = uncap3(s); 
     } 
     end = System.currentTimeMillis(); 
     System.out.println("3: " + (end - start)); 

     System.exit(0); 
    } 

    // The simple, direct version; also allows the library to handle 
    // locales and Unicode correctly 
    private static final String uncap1(String s) 
    { 
     return s.substring(0,1).toLowerCase() + s.substring(1); 
    } 

    // This will *not* handle locales and unicode correctly 
    private static final String uncap2(String s) 
    { 
     return Character.toLowerCase(s.charAt(0)) + s.substring(1); 
    } 

    // This will *not* handle locales and unicode correctly 
    private static final String uncap3(String s) 
    { 
     StringBuffer sb; 

     sb = new StringBuffer(s); 
     sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); 
     return sb.toString(); 
    } 
} 

我混了在各種測試中的順序(走動它們並重新編譯),以避免加速時間問題(並試圖無論如何強迫一些)。非常不科學,但uncap1一直比uncap2uncap3慢約40%。這並不重要,我們所談論的是在Intel Atom處理器上百萬次迭代中400ms的差異。 :-)

所以:我會用簡單,直接的代碼包裝在一個實用函數中。

+0

在許多情況下,這種microbenchmark不適用於JVM。見http://www.ibm.com/developerworks/java/library/j-benchmark1.html – deamon 2010-03-15 14:06:43

+0

@deamon:我不會感到驚訝。 :-)(感謝鏈接,必須在某個時候給它閱讀)。我確實說過「不科學」,並且他確實不應該擔心,直到或者除非有特定的性能問題需要解決。 – 2010-03-15 14:09:57

+0

幹得好!只需看看Common-Lang 3.0中如何實現非大寫方法(或者可能已經在當前版本2.3中以相同方式實現):新的StringBuilder(strLen).append(Character.toLowerCase(str.charAt(0)))。追加(str.substring(1))的toString(); – Maxym 2010-03-15 14:10:56

1

注意字符串中的任何字符函數。由於unicode,它並不總是1對1的映射。堅持基於字符串的方法,除非字符真的是你想要的。正如其他人所建議的,那裏有字符串實用程序,但即使您不想將它們用於您的項目,也可以在工作時自己創建一個。你可以做的最糟糕的事情就是做一個小寫字母的特殊函數,並將它隱藏在一個類中,然後在12個不同的地方使用相同的代碼。把它放在一個可以輕鬆分享的地方。

1

使用StringBuffer

buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0))); 
+3

你想避免這些東西的字符版本:*「一般來說,應該使用String.toLowerCase()來將字符映射爲小寫字符串大小寫映射方法比字符大小寫映射方法。字符串大小寫映射方法可以執行區域敏感映射,上下文敏感映射和1:M字符映射,而字符大小寫映射方法不能。「* - http://java.sun.com/javase/6/docs /api/java/lang/Character.html#toLowerCase%28char%29另外,顯式使用'StringBuffer'作爲一個'String' concat實際上不會幫助perf(並且可能會阻礙)。 – 2010-03-15 14:04:03

相關問題