我正在解决的问题是将所有字符串替换为另一个字符串。
我使用String.replaceAll在codingbat.com上相当容易地解决了这个问题,直到第一个String不再包含其他String为止。
但是,我不喜欢这种方法,因为它很慢。我试图在这个网站上搜索更有效的方法,并遇到了这些问题:
Fastest way to perform a lot of strings replace in Java
String.replaceAll is considerably slower than doing the job yourself
他们使用StringUtils和Patterns解决了这个问题。我仍然认为这些方法太慢了!
当我编写像这样的问题时,我喜欢用Java在两秒钟内获得运行时。我用一个1,000,000个字符的字符串来测试它。 String.replaceAll超过两秒,其他两种方法也是如此。
有没有人有这个问题的快速解决方案?谢谢!
编辑:不幸的是,我收到的答案仍然运行得太慢。是的,我的意思是创建一个新的String,而不是更改旧的String,抱歉这个错误。
我不确定它是如何工作的,但我认为循环每个字符并检查可能有效。算法的东西。
答案 0 :(得分:1)
字符串是不可变的,因此您无法从中删除内容。这意味着您需要创建一个没有要删除的东西的新String。当您使用String.replace时,它几乎就是它所做的:它创建一个新的String。
谨防String.replaceAll,因为它使用的是每次调用时都会编译的正则表达式(所以永远不要在长循环中使用它)。这可能是你的问题。
如果需要使用正则表达式,请使用Pattern类编译正则表达式并重用该实例,为您处理的每个字符串创建一个新的Matcher。如果你不重用你的Pattern实例,那就会很慢。
如果您不需要正则表达式,StringUtils有一个不依赖正则表达式的replaceEach()。
如果您正在处理大字符串。您可能希望以流式方式执行操作并循环遍历字符并将字符复制到StringBuilder。
或者,您可以使用正则表达式在String中搜索特定模式并循环搜索它找到的匹配项,并为每个匹配项添加从上一个匹配到当前匹配的所有内容到StringBuilder。
答案 1 :(得分:1)
问题是你的字符串很大,你只想移动/复制一次,所有使用多次调用替换的解决方案仍然会做大量不必要的工作。
您真正想要使用的是Apache StringUtils.replaceEachRepeatedly,因为该方法只处理搜索多个字符串,而只构建一个结果字符串。
答案 2 :(得分:0)
除了每个方法(替换,StringUtils或Patterns,...)之外,只有一个Thread工作。
如果您可以将该线程完成的工作拆分为两个或更多,例如每个Thread在字符串中的特定位置运行到另一个,您将能够快速解决。
棘手的部分是分割工作然后将它们连接在一起。 这将取决于你如何读取字符串,例如,你在哪里写它。
问候,
答案 3 :(得分:0)
前段时间我遇到了同样的问题并且来到这篇文章:Replace all occurrences of a String using StringBuilder?
使用帖子中给出的实现:
public static void main(String[] args) {
String from = "A really long string full of ands and ors";
String replaceFrom = "and";
String replaceTo = "or";
long initTime = System.nanoTime();
String result1 = from.replace(replaceFrom, replaceTo);
System.out.println("Time1: " + (System.nanoTime() - initTime));
System.out.println(result1);
StringBuilder sb1 = new StringBuilder(from);
initTime = System.nanoTime();
replaceAll(sb1, replaceFrom, replaceTo);
System.out.println("Time1: " + (System.nanoTime() - initTime));
System.out.println(sb1.toString());
}
// From https://stackoverflow.com/questions/3472663/replace-all-occurences-of-a-string-using-stringbuilder
public static void replaceAll(StringBuilder builder, String from, String to) {
int index = builder.indexOf(from);
while (index != -1) {
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
对第二种解决方案更好性能的解释是它继承了StringBuilder,一个可变对象而不是String是一个不可变对象。有关更好的解释,请参阅Immutability of Strings in Java。
此解决方案将同时使用StringBuffer和StringBuilder,但正如Difference between StringBuilder and StringBuffer中所述,StringBuffer已同步且StringBuilder未同步,因此如果您不需要同步,则最好使用StringBuilder。
答案 4 :(得分:0)
我刚试过这个,结果是:
100960923
197642683484
import java.util.Stack;
public class Test {
public static String removeAll(final String stringToModify, final String stringToFindAndRemove) {
if (stringToModify==null||stringToModify.length()==0) return new String(stringToModify);
if (stringToFindAndRemove==null||stringToFindAndRemove.length()==0) return new String(stringToModify);
if (stringToModify.length()<stringToFindAndRemove.length()) return new String(stringToModify);
int lastChar = 0;
int buffPos=0;
Stack<Integer>stack = new Stack<Integer>();
char[] chars = stringToModify.toCharArray();
char[] ref = stringToFindAndRemove.toCharArray();
char[] ret = new char[chars.length];
for (int a=0;a<chars.length;a++) {
if (chars[a]==ref[buffPos]) {
if (buffPos==ref.length-1) {
buffPos=0;
stack.pop();
} else {
if (buffPos==0) stack.push(lastChar);
buffPos++;
}
} else {
if (buffPos!=0) {
for (int b=0;b<buffPos;b++) {
ret[lastChar]=ref[b];
lastChar++;
}
a--;
buffPos = 0;
} else {
ret[lastChar]=chars[a];
lastChar++;
}
}
if (stack.size()>0&&(lastChar-stack.peek()>=ref.length)) {
while(stack.size()>0 && (lastChar-stack.peek()>=ref.length)) {
int top = stack.pop();
boolean f = true;
for (int foo=0;foo<ref.length;foo++) {
if (ret[top+foo]!=ref[foo]) {
f=false;
break;
}
}
if (f) lastChar=top;
}
}
}
if (buffPos!=0) {
for (int b=0;b<buffPos;b++) {
ret[lastChar]=ref[b];
lastChar++;
}
}
char[] out = new char[lastChar];
System.arraycopy(ret,0,out,0,lastChar);
return new String(out);
}
public static void main(final String[] args) {
StringBuffer s = new StringBuffer();
StringBuffer un = new StringBuffer();
for (int a=0;a<100000;a++) {
s.append("s");
un.append("un");
}
StringBuffer h = new StringBuffer(s);
h.append(un);
h.append("m");
String huge = h.toString();
String t = "sun";
long startTime = System.nanoTime();
String rep = removeAll(huge,t);
long endTime = System.nanoTime();
long duration = (endTime - startTime);
//System.out.println(rep);
System.out.println(duration);
startTime = System.nanoTime();
rep = new String(huge);
int pos = rep.indexOf(t);
while (pos!=-1) {
rep = rep.replaceAll(t,"");
pos = rep.indexOf(t);
}
endTime = System.nanoTime();
duration = (endTime - startTime);
//System.out.println(rep);
System.out.println(duration);
}
}
我有兴趣看一下这台机器有多快。因为我的老板认为我的机器足够快! :)