簡體   English   中英

String.trim()比String.replace()更快嗎?

[英]Is String.trim() faster than String.replace()?

假設有一個像" world "這樣的字符串。 此字符串僅在前端和末尾有空白。 trim()replace()更快嗎?

我使用了替換一次,我的導師說不要使用它,因為trim()可能更快。

如果沒有, trim()的優點是什么比replace()

如果我們查看方法的源代碼

replace()

 public String replace(CharSequence target, CharSequence replacement) {
    String tgtStr = target.toString();
    String replStr = replacement.toString();
    int j = indexOf(tgtStr);
    if (j < 0) {
        return this;
    }
    int tgtLen = tgtStr.length();
    int tgtLen1 = Math.max(tgtLen, 1);
    int thisLen = length();
    int newLenHint = thisLen - tgtLen + replStr.length();
    if (newLenHint < 0) {
        throw new OutOfMemoryError();
    }
    StringBuilder sb = new StringBuilder(newLenHint);
    int i = 0;
    do {
        sb.append(this, i, j).append(replStr);
        i = j + tgtLen;
    } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
    return sb.append(this, i, thisLen).toString()
}

trim()

public String trim() {
    int len = value.length;
    int st = 0;
    char[] val = value;    /* avoid getfield opcode */
    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

正如您所看到的, replace()調用多個其他方法並遍歷整個String ,而trim()只是遍歷String的開頭和結尾,直到該字符不是空格。 因此,在嘗試刪除單詞前后的空格的單一方面, trim()更有效。


我們可以對此進行一些基准測試:

public static void main(String[] args) {
       long testStartTime = System.nanoTime();;
       trimTest();
       long trimTestTime = System.nanoTime() - testStartTime;
       testStartTime = System.nanoTime();     
       replaceTest();
       long replaceTime = System.nanoTime() - testStartTime;           
       System.out.println("Time for trim(): " + trimTestTime);
       System.out.println("Time for replace(): " + replaceTime);            
}

public static void trimTest() {
    for(int i = 0; i < 1000000; i ++) {     
        new String("  string   ").trim();
    }
}
public static void replaceTest() {
    for(int i = 0; i < 1000000; i ++) {     
        new String("  string   ").replace(" ", "");
    }
}

輸出:

Time for trim(): 53303903
Time for replace(): 485536597
//432,232,694 difference

trim()肯定更快輸入,是的。 它不需要任何參數。

理解你在哪里嘗試也要快得多。 您試圖修剪字符串,而不是用空字符串替換它包含的所有空格,從其他上下文知道字符串的開頭和結尾只有空格

無論你如何看待它,確實要快得多。 不要使試圖閱讀代碼的人的生活復雜化。 大多數時候,幾個月后,或者至少是你不討厭的人。

假設編寫Java庫代碼的人員做得很好1 ,你可以假設一個特殊用途的方法(比如trim() )會快,而且可能比通用方法更快(比如replace(...) )做同樣的事情。

兩個原因:

  • 如果特殊用途方法較慢,則可以將其實現重寫為對通用方法的等效調用,從而在大多數情況下使性能等效。 一個稱職的程序員會這樣做,因為它可以降低維護成本。

  • 在特殊用途方法中,可能會出現不適用於通用情況的優化。

在這種情況下,我們知道trim()需要查看字符串的開頭和結尾......而replace(...) 需要查看字符串中的所有字符。 (我們可以從相應方法的描述中推斷出這一點。)

如果我們假設“能力”,那么我們可以推斷開發人員將完成分析而不是次優地實現trim() 2 ; 即他們不會編碼trim()來檢查所有字符。


在通用目的上使用特殊用途方法還有另一個原因。 它使您的代碼更簡單,更易於閱讀,並且更容易檢查是否正確。 這可能比性能更重要

這顯然適用於trim()replace(...)


1 - 我們可以在這種情況下。 很多人都在關注這段代碼,很多人會大聲抱怨性能問題。

2 - 不幸的是,它並不總是那么簡單。 庫方法需要針對“典型”行為進行優化,但還需要避免邊緣情況下的病態性能。 並不總是能夠實現這兩件事。

修剪將修剪外部字符,直到它們是非空白區域。 我相信他們會修剪空間,標簽和新線條。

替換將掃描整個字符串(因此,它可能是一個句子)並將內部“”替換為“”,基本上將它們壓縮在一起。

它們有不同的用例,顯然1是清理用戶輸入,另一個是更新字符串,其中匹配項與其他內容相同。

話雖如此,運行時間:替換將在N次運行,因為它將查找所有匹配的字符。 修剪將在O(N)中運行,但很可能只是每端的幾個字符。

我認為修剪背后的想法來自於人們會輸入和輸入內容但在提交表單之前意外按空格,本質上是試圖保存字段“Foo”而不是“Foo”

s.trim()縮短了String s 這意味着不必將字符從索引移動到另一個索引。 它開始於第一個字符( s.toCharArray()[0]的的String ,縮短了String直到第一非空白字符發生逐字符。 它的工作方式與最后縮短String方式相同。 所以它壓縮了String 如果一個String沒有開頭和結尾的空格trim將是檢查的第一個和最后一個字符之后准備就緒。

" world ".trim()情況下,需要兩個步驟:一個用於刪除第一個前導空格,因為它在第一個索引上,第二個用於刪除最后一個空格,因為它在最后一個索引上。

" world ".replace(" ", "")至少需要n = " world ".length()步驟。 如果必須更換,必須檢查每個字符。 但是如果我們考慮到String.replace(...)的實現需要編譯一個Pattern ,構建一個Matcher然后替換所有匹配的區域,那么與縮短一個String相比,它似乎相當復雜。

我們還必須考慮" world ".replace(" ", "")不能替換空格,而只能替換String " " 由於String replace(CharSequence target, CharSequence replacement)使用Pattern.LITERAL編譯目標,我們不能使用字符類\\ s 為了更准確,我們必須將" world ".trim()" world ".replaceAll("\\\\s", "") 它仍然不一樣,因為String trim()的空格被定義為s.toCharArray()每個c c <= ' '

總結: String.trim()應該更快 - 特別是對於長字符串

描述方法如何工作基於Java 8中String的實現。但是實現可以改變。

但問題應該是:你打算用字符串做什么? 你想修剪它還是替換一些字符? 根據它使用相應的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM