繁体   English   中英

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

[英]What should I change for optimize the replace method?

我正在创建一种方法来了解字符串中有多少次“ 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
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的替换结果,但是某些样式检查器将首选equals。 长度相等就足够了。

当然,替换的数量是长度减少/ 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提供基准测试。

首先,我使用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();
}

在上述String这样的测试用例中,对于大多数随机测试用例,此版本的replace()肯定比您快得多 ,因为它可以在1次迭代中进行1次以上的替换,并且不使用任何计数器。
处理诸如此类的情况时, StringBuilder会更高效,更快:

RARARARARARARARARARAVVVVVVVVVV

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

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

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

如果您使用recursion ,它将更快。

public class E{

    private int cont;

    private static int replace(String cad){
        StringBuilder sb = new StringBuilder(cad);

        if(sb.indexOf("RAV") > -1){
            sb.replace(sb.indexOf("RAV"), sb.indexOf("RAV") + 3, "");
            cont++;
            return replace(sb.toString())}
        else{
            return cont; 
        }
    }

    public static void main(String[] args) {
        cont = 0;
        String[] arr = new String[]{"RARAVV", "VAR", "RAVV"};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(replace(arr[i]));
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM