簡體   English   中英

替換字符串中字符的有效方法(java)?

[英]Efficient way to replace chars in a string (java)?

我正在編寫一個小型 JAVA 程序,它:

  • 將文本作為字符串
  • 需要 2 個字符數組

我試圖做的聽起來像是“查找和替換”,但它不一樣,所以我認為清除它很重要。

無論如何,我想獲取此文本,查找第一個數組中的任何字符是否與文本中的字符匹配,如果匹配,則將其替換為第二個字符數組中的匹配字符(根據索引)。

我會用一個例子來解釋:假設我的文本(字符串)是:“java 太棒了!”; 我有 2 個數組 (char[]):“absm”和“!@*$”。

期望的結果是將 'a' 更改為 '!' , 'b' 到 '@' 等等.. 意味着結果文本將是:

“java太棒了!” 改為 -> "j@v@ i* @w*o$e!"

這樣做的最有效方法是什么,為什么? 我想過循環文本,但后來我發現它不是那么有效。

(可以使用StringBuilder /String 類)

StringBuilder sb = new StringBuilder(text);
    for(int i = 0; i<text.length(); i ++)
    {
        for (int j = 0; j < firstCharArray.length;j++)
        {
            if (sb.charAt(i) == firstCharArray[j])
            {
                sb.setCharAt(i, secondCharArray[j]);
                break;
            }

        }
    }

這種方式很有效,因為它使用 StringBuilder 來更改字符(如果您使用字符串,則每次都必須創建新的,因為它們是不可變的。)此外,它還最大限度地減少了您必須執行的傳遞次數(1 次傳遞)文本字符串和 n 通過第一個數組,其中 n = text.length())

我猜您正在尋找StringUtils.replaceEach ,至少作為參考。

你需要它有多高效? 你這樣做是為了數百、數千、數百萬個單詞嗎???

我不知道它是否最有效,但是您可以在每個可能的標記上使用 string indexOf()方法,它會告訴您它是否存在,然后您可以同時用相應的索引替換該索引來自另一個數組的字符。

Codewise,類似於(順便說一下,這是半偽代碼):

for(each of first array) {
    int temp = YourString.indexOf(current array field);
    if (temp >=0) {
        replace with other array
    }
}

將您擁有的 2 個數組放在 Map 中

Map<Character, Character> //or Map of Strings

其中鍵是“a”、“b”等……而值是您要替換的字符 - “@”等……

然后只需用值替換字符串中的鍵。

對於像這樣的小東西, indexOf() 搜索可能比地圖更快,同時“避免”接受答案的內部循環。 當然,循環仍然存在,在 String.indexOf() 內部,但它很可能被 JIT 編譯器優化為一個很好的方式,因為它被大量使用。

static String replaceChars(String source, String from, String to)
{
    StringBuilder dest = new StringBuilder(source);
    for ( int i = 0; i < source.length(); i++ )
    {
        int foundAt = from.indexOf(source.charAt(i));
        if ( foundAt >= 0 )
            dest.setCharAt(i,to.charAt(foundAt));
    }
    return dest.toString();
}

更新:Oracle/Sun JIT 至少在某些處理器上為 indexOf() 使用SIMD ,使其比人們猜測的更快。

此實用程序類替換 String 的一個字符或一組字符 它相當於 bash tr和 perl tr/// ,也就是音譯。

/**
 * Utility class that replaces chars of a String, aka, transliterate.
 * 
 * It's equivalent to bash 'tr' and perl 'tr///'.
 *
 */
public class ReplaceChars {

    public static String replace(String string, String from, String to) {
        return new String(replace(string.toCharArray(), from.toCharArray(), to.toCharArray()));
    }

    public static char[] replace(char[] chars, char[] from, char[] to) {

        char[] output = chars.clone();
        for (int i = 0; i < output.length; i++) {
            for (int j = 0; j < from.length; j++) {
                if (output[i] == from[j]) {
                    output[i] = to[j];
                    break;
                }
            }
        }
        return output;
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        // Example from: https://en.wikipedia.org/wiki/Caesar_cipher
        String string = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";
        String from = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String to = "XYZABCDEFGHIJKLMNOPQRSTUVW";

        System.out.println();
        System.out.println("Cesar cypher: " + string);
        System.out.println("Result:       " + ReplaceChars.replace(string, from, to));
    }
}

這是輸出:

Cesar cypher: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
Result:       QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD

由於知道是否應該替換字符的唯一方法是檢查它,因此您(或任何 util 方法)必須一個接一個地遍歷整個文本。 您永遠無法實現比O(n)更好的復雜性(n 是文本中的字符數)。

暫無
暫無

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

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