[英]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
您认为StringBuilder
比String
快吗?
考虑以下方法:
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.