什么是替换字符串中的许多字符的有效方法?

时间:2011-03-29 09:46:13

标签: java optimization string

Java中的字符串处理是我努力学习做得好的事情。目前我想接受一个字符串并替换我找到的任何字符。

这是我目前效率低下的(有点愚蠢的IMO)功能。它只是为了工作而写的。

public String convertWord(String word)
{
    return word.toLowerCase().replace('á', 'a')
                             .replace('é', 'e')
                             .replace('í', 'i')
                             .replace('ú', 'u')
                             .replace('ý', 'y')
                             .replace('ð', 'd')
                             .replace('ó', 'o')
                             .replace('ö', 'o')
                             .replaceAll("[-]", "")
                             .replaceAll("[.]", "")
                             .replaceAll("[/]", "")
                             .replaceAll("[æ]", "ae")
                             .replaceAll("[þ]", "th");
}

我跑了1.000.000次,耗时8182ms。那么我应该如何进行更改此功能以提高效率呢?

找到解决方案:

将功能转换为此

public String convertWord(String word)
{
    StringBuilder sb = new StringBuilder();

    char[] charArr = word.toLowerCase().toCharArray();

    for(int i = 0; i < charArr.length; i++)
    {
        // Single character case
        if(charArr[i] == 'á')
        {
            sb.append('a');
        }
        // Char to two characters
        else if(charArr[i] == 'þ')
        {
            sb.append("th");
        }
        // Remove
        else if(charArr[i] == '-')
        {
        }
        // Base case
        else
        {   
            sb.append(word.charAt(i));
        }
    }

    return sb.toString();
}

运行此功能1.000.000次需要518ms。所以我认为这足够有效。谢谢你们的帮助:)

9 个答案:

答案 0 :(得分:20)

您可以创建一个String []表,其长度为Character.MAX_VALUE。 (包括映射到小写)

随着替换变得更加复杂,执行它们的时间将保持不变。

private static final String[] REPLACEMENT = new String[Character.MAX_VALUE+1];
static {
    for(int i=Character.MIN_VALUE;i<=Character.MAX_VALUE;i++)
        REPLACEMENT[i] = Character.toString(Character.toLowerCase((char) i));
    // substitute
    REPLACEMENT['á'] =  "a";
    // remove
    REPLACEMENT['-'] =  "";
    // expand
    REPLACEMENT['æ'] = "ae";
}

public String convertWord(String word) {
    StringBuilder sb = new StringBuilder(word.length());
    for(int i=0;i<word.length();i++)
        sb.append(REPLACEMENT[word.charAt(i)]);
    return sb.toString();
} 

答案 1 :(得分:8)

我的建议是:

  • 将String转换为char []数组
  • 遍历数组,逐个测试每个字符(例如使用switch语句)并在需要时替换它
  • 将char []数组转换回String

我认为这可能是您在纯Java中获得的最快性能。

编辑:我注意到你正在做一些改变字符串长度的更改。在这种情况下,同样的原则适用,但是您需要保留两个数组并分别递增源索引和目标索引。如果用完目标空间,您可能还需要调整目标数组的大小(即重新分配更大的数组并将现有目标数组进行数组复制)

答案 2 :(得分:5)

我的实施基于查找表。

public static String convertWord(String str) {
    char[] words = str.toCharArray();
    char[] find = {'á','é','ú','ý','ð','ó','ö','æ','þ','-','.',
            '/'};
    String[] replace = {"a","e","u","y","d","o","o","ae","th"};
    StringBuilder out = new StringBuilder(str.length());
    for (int i = 0; i < words.length; i++) {
        boolean matchFailed = true;
        for(int w = 0; w < find.length; w++) {
            if(words[i] == find[w]) {
                if(w < replace.length) {
                    out.append(replace[w]);
                }
                matchFailed = false;
                break;
            }
        }
        if(matchFailed) out.append(words[i]);
    }
    return out.toString();
}

答案 3 :(得分:2)

我的第一选择是使用StringBuilder因为你需要从字符串中删除一些字符。

第二个选择是迭代抛出字符数组并将处理过的字符添加到字符串的另一个数组中。然后,您需要复制数组以修剪可能未使用的位置。

在那之后,我会做一些性能测试,看看女巫更好。

答案 4 :(得分:0)

我怀疑,你真的可以加速'角色替换'。对于正则表达式替换的情况,您可以事先编译正则表达式

答案 5 :(得分:0)

使用函数String.replaceAll。 与你想要的相似的好文章:link

答案 6 :(得分:0)

任何时候我们遇到这样的问题我们使用正则表达式它们是迄今为止处理你要做的事情的最快方法。

您是否已经尝试过正则表达式?

答案 7 :(得分:0)

我认为效率低下的是你要再次检查已被替换的字符,这是没用的。

我会得到String实例的charArray,迭代它,并为每个字符垃圾邮件一系列if-else这样:

char[] array = word.toCharArray();
for(int i=0; i<array.length; ++i){
    char currentChar = array[i];
    if(currentChar.equals('é'))
        array[i] = 'e';
    else if(currentChar.equals('ö'))
        array[i] = 'o';
    else if(//...
}

答案 8 :(得分:0)

我刚刚实现了这个实用程序类,它替换了一个字符或一个字符串的一组字符。它等效于bash tr和perl tr///,也就是音译。希望对您有所帮助!

package your.package.name;

/**
 * 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