为了优化替换方法,我应该更改什么?

时间:2019-01-29 13:32:54

标签: java replace

我正在创建一种方法来了解字符串中有多少次“ RAV”。 我的程序可以运行,但是当字符串包含+10.000个字符时,它应该更快。

首先,我使用String,然后使用StringBuilder,它速度更快,但还不够。

public class E{

    private static int replace(String cad){
        StringBuilder sb = new StringBuilder(cad);
        int cont = 0;
        while (sb.indexOf("RAV") > -1 && cont < 50000) {
            sb.replace(sb.indexOf("RAV"), sb.indexOf("RAV") + 3, "");
            cont++;
        }
        return cont;
    }
    public static void main(String[] args) {
        String[] arr = new String[]{"RARAVV", "VAR", "RAVV"};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(replace(arr[i]));
        }
    }
}

预期输出为

2
0
1

4 个答案:

答案 0 :(得分:2)

private static int replace(String cad) {
    int originalLength = cad.length();
    for (;;) {
        String cad2 = cad.replace("RAV", "");
        if (cad2.length() == cad.length()) {
            break;
        }
        cad = cad2;
    }
    return (originalLength - cad.length()) / "RAV".length();
}

首先将indexOf放入变量中,使其使用3次。 String.replace可以进行多次替换。表达式的还原则具有不同的顺序,但是对于“ RAV”而言,不会产生不同的结果。

在上面,您可以测试cad2 == cad的替换结果,但某些样式检查器将首选等于。长度相等就足够了。

当然,替换的数量是长度减少/ 3。


实际测量结果显示String.replace(String, String)缓慢:

private static int replace(String cad) {
    // Could try to shorten string: cad = cad.replaceAll("[^RAV]+", "e");
    StringBuilder sb = new StringBuilder(cad);
    int pos0 = 0;
    for (;;) {
        int pos = sb.indexOf("RAV", pos0);
        if (pos == -1) {
            break;
        }
        sb.delete(pos, pos + 3);
        // Continue searching 2 chars before.
        pos0 = Math.max(0, pos - 2); // RA[RAV]V
    }
    return (cad.length() - sb.length()) / 3;
}

感谢使用@GPI进行基准测试。

答案 1 :(得分:1)

  

首先我使用String,然后使用StringBuilder,它速度更快

确定吗?您使用了哪些测试用例?
为此:

RAVRAVRAVRAVRAVRAVRAVRAVRAVRAV

您认为StringBuilderString快吗?
考虑这种方法:

public static int replace(String cad, String pattern){
    String str = cad;
    do {
        str = str.replace(pattern, "");
    } while (str.contains(pattern));
    return (cad.length() - str.length()) / pattern.length();
}

在像上述replace()这样的测试用例中,对于大多数随机测试用例,该版本的String肯定比您快,因为它可以提供1次迭代1次替换,不使用任何计数器。
当您处理以下情况时,StringBuilder会更高效,更快:

RARARARARARARARARARAVVVVVVVVVV

答案 2 :(得分:1)

这是我对线性算法的看法。不是最通用或最漂亮的代码,而是它说明了这个想法。 对该字符串仅进行一次扫描,我们不会向后或向前看,这会在字符串长度上产生线性影响。

对于更长的字符串,这应该比基于“替换”的算法快得多。

public class Main {

    private static class StateFrame {
        int matched;
        StateFrame previous;
    }

    private static int count(String cad) {
        StateFrame state = new StateFrame();
        final int len = cad.length();
        int result = 0;
        for (int i = 0; i < len; i++) {
            final char ch = cad.charAt(i);
            if (ch == 'R') {
                if (state.matched == 0) {
                    state.matched = 1;
                } else {
                    StateFrame next = new StateFrame();
                    next.previous = state;
                    state = next;
                    state.matched = 1;
                }
            } else if (ch == 'A') {
                if (state.matched == 1) {
                    state.matched = 2;
                } else {
                    state.previous = null;
                    state.matched = 0;
                }
            } else if (ch == 'V') {
                if (state.matched == 2) {
                    result++;
                    if (state.previous == null) {
                        state.matched = 0;
                    } else {
                        state = state.previous;
                    }
                } else {
                    state.previous = null;
                    state.matched = 0;
                }
            } else {
                state.previous = null;
                state.matched = 0;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        String[] arr = new String[] { "RARAVV", "VAR", "RAVV", "RRAVRXXXAV", "RARRAVAVV", "RRAVARAVV", "RRARAVVARAVV" };
        for (String anArr : arr) {
            System.out.printf("%s %d%n", anArr, count(anArr));
        }
    }
}

输出为

RARAVV 2
VAR 0
RAVV 1
RRAVRXXXAV 1
RARRAVAVV 3
RRAVARAVV 3
RRARAVVARAVV 4

答案 3 :(得分:0)

如果您使用Title Status title2 fail 进行此操作,将会更快。

recursion