摆脱字符串中第一个标记的最快方法是什么?到目前为止,我已经尝试过这个:
String parentStringValue = this.stringValue.split(" ", 2)[1];
它的内存和速度极低(当15个字长的字符串重复数百万次时)。假设字符串由用空格分隔的标记组成。
答案 0 :(得分:6)
substring( x )
vs split( x )
vs Regex 答案已编辑:已修正主要缺陷
在我的基准测试中纠正了一些相当重大的缺陷后(正如Jay Askren在评论中指出的那样)。 StringBuilder
方法以最快的速度出现(尽管这假定StringBuilder
对象是预先创建的),子串出现在第二位。 split()
倒数第二,比StringBuilder
方法慢10倍。
ArrayList<String> strings = new ArrayList<String>();
ArrayList<StringBuilder> stringBuilders = new ArrayList<StringBuilder>();
for(int i = 0; i < 1000; i++) strings.add("Remove the word remove from String "+i);
for(int i = 0; i < 1000; i++) stringBuilders.add(new StringBuilder(i+" Remove the word remove from String "+i));
Pattern pattern = Pattern.compile("\\w+\\s");
// StringBuilder method
before = System.currentTimeMillis();
for(int i = 0; i < 5000; i++){
for(StringBuilder s : stringBuilders){
s.delete(0, s.indexOf(" ") + 1);
}
}
after = System.currentTimeMillis() - before;
System.out.println("StringBuilder Method Took "+after);
// Substring method
before = System.currentTimeMillis();
for(int i = 0; i < 5000; i++){
for(String s : strings){
String newvalue = s.substring(s.indexOf(" ") + 1);
}
}
after = System.currentTimeMillis() - before;
System.out.println("Substring Method Took "+after);
//Split method
before = System.currentTimeMillis();
for(int i = 0; i < 5000; i++){
for(String s : strings){
String newvalue = s.split(" ", 2)[1];
System.out.print("");
}
}
after = System.currentTimeMillis() - before;
System.out.println("Your Method Took "+after);
// Regex method
before = System.currentTimeMillis();
for(int i = 0; i < 5000; i++){
for(String s : strings){
String newvalue = pattern.matcher(s).replaceFirst("");
}
}
after = System.currentTimeMillis() - before;
System.out.println("Regex Method Took "+after);
我按照随机顺序运行上述内容,经过热身,连续取平均值,将操作次数从500万增加到3000万,然后每次运行十次,然后继续下一次。无论哪种方式,最快到最慢的顺序保持不变。以下是上述代码的一些示例输出;
StringBuilder Method Took 203
Substring Method Took 588
Split Method Took 1833
Regex Method Took 2517
值得一提的是,使用长度大于1的split()
调用String
只会在其实现中使用Regex,因此使用split()
和{Pattern
之间应该没有区别{1}}对象。
答案 1 :(得分:4)
无需拆分和创建数组,只需使用substring
即可String str="I want to remove I";
String parentStringValue = str.substring(str.indexOf(" ")+1);
System.out.println(parentStringValue);
Out put:
want to remove I
答案 2 :(得分:2)
您可以将String.substring
和String.indexOf
组合使用。
有些事情:
// TODO check indexOf does not return -1
this.stringValue.substring(this.stringValue.indexOf(" ") + 1)
答案 3 :(得分:1)
试试这个:
String s = "This is a test";
System.out.println(s.replaceFirst("\\w+\\s", ""));
答案 4 :(得分:1)
在执行字符串操作时尝试使用StringBuffer或StringBuilder,这样它就不会留下大量新的未使用对象并导致内存效率低下,因为重复数百万次,如上所述
答案 5 :(得分:1)
Rudi的基准测试有很多问题,包括不公平和错误地偏爱分裂方法。所以我采用了他的基准并对其进行了改进。如果你有一堆StringBuilders,StringBuilder的方法稍微快一点,但是如果你需要先从字符串转换它们,那就很慢了。子字符串方法是下一个最快的方法,如果你有字符串而不是字符串构建器,你应该使用它。 CommonsLang是下一个最快的,子串方法和CommonsLang方法比使用split快4到5倍。 String.replaceFirst()使用正则表达式并且非常慢,因为它需要在每次运行时编译正则表达式,这使运行时间加倍。即使没有编译步骤,它也明显慢于其他步骤。
以下是基准测试的代码。您需要将ApacheCommonsLang添加到类路径中才能运行它。
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
/**
*
*/
public class StringTest {
public static void main(String[] args) {
int numIterations = 100000;
int numRuns = 10;
ArrayList<String> strings = new ArrayList<String>();
for(int i = 0; i < 1000; i++) strings.add("Remove the word remove from String "+i);
//Your method
long before = 0;
long after = 0;
for(int j=0; j < numRuns; j++) {
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
for(String s : strings){
String newvalue = s.split(" ", 2)[1];
// System.out.println("split " + newvalue);
}
}
after = System.currentTimeMillis() - before;
System.out.println("Split Took "+after + " ms");
}
// Substring method
for(int j=0; j < numRuns; j++) {
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
for(String s : strings){
String newvalue = s.substring(s.indexOf(" ") + 1);
}
}
after = System.currentTimeMillis() - before;
System.out.println("Substring Took "+after + " ms");
}
// Apache Commons Lang method
before = System.currentTimeMillis();
for(int j=0; j < numRuns; j++) {
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
for (String s : strings) {
String parentStringValue = StringUtils.substringAfter(s, " ");
}
}
after = System.currentTimeMillis() - before;
System.out.println("CommonsLang Took "+after + " ms");
}
for(int j=0; j < numRuns; j++) {
long deleteTime = 0l;
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
List<StringBuilder> stringBuilders = new ArrayList<StringBuilder>();
for (String s : strings) {
stringBuilders.add(new StringBuilder(s));
}
long beforeDelete = System.currentTimeMillis();
for (StringBuilder s : stringBuilders) {
s.delete(0, s.indexOf(" ") + 1);
}
deleteTime+=(System.currentTimeMillis() - beforeDelete);
}
after = System.currentTimeMillis() - before;
System.out.println("StringBuilder Delete " + deleteTime + " ms out of " + after + " total ms");
}
// Faster Regex method
Pattern pattern = Pattern.compile("\\w+\\s");
for(int j=0; j < numRuns; j++) {
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
for (String s : strings) {
String newvalue = pattern.matcher(s).replaceFirst("");
}
}
after = System.currentTimeMillis() - before;
System.out.println("Faster Regex Took "+after + " ms");
}
// Slow Regex method
for(int j=0; j < numRuns; j++) {
before = System.currentTimeMillis();
for(int i = 0; i < numIterations; i++){
for (String s : strings) {
String newvalue = s.replaceFirst("\\w+\\s", "");
}
}
after = System.currentTimeMillis() - before;
System.out.println("Slow Regex Took " + after + " ms");
}
}
}
在装有I7处理器的机器上,我得到了以下结果:
Split Took 10552 ms
Split Took 10298 ms
Split Took 10297 ms
Split Took 10292 ms
Split Took 10527 ms
Split Took 10356 ms
Split Took 10324 ms
Split Took 10283 ms
Split Took 10375 ms
Split Took 10346 ms
Substring Took 2385 ms
Substring Took 2354 ms
Substring Took 2363 ms
Substring Took 2358 ms
Substring Took 2361 ms
Substring Took 2367 ms
Substring Took 2370 ms
Substring Took 2350 ms
Substring Took 2354 ms
Substring Took 2397 ms
CommonsLang Took 2462 ms
CommonsLang Took 2461 ms
CommonsLang Took 2422 ms
CommonsLang Took 2426 ms
CommonsLang Took 2479 ms
CommonsLang Took 2441 ms
CommonsLang Took 2440 ms
CommonsLang Took 2420 ms
CommonsLang Took 2418 ms
CommonsLang Took 2421 ms
StringBuilder Delete 2302 ms out of 5904 total ms
StringBuilder Delete 2272 ms out of 5908 total ms
StringBuilder Delete 2241 ms out of 5879 total ms
StringBuilder Delete 2263 ms out of 5856 total ms
StringBuilder Delete 2285 ms out of 5858 total ms
StringBuilder Delete 2305 ms out of 5864 total ms
StringBuilder Delete 2287 ms out of 5854 total ms
StringBuilder Delete 2238 ms out of 5890 total ms
StringBuilder Delete 2335 ms out of 5875 total ms
StringBuilder Delete 2301 ms out of 5863 total ms
Faster Regex Took 18387 ms
Faster Regex Took 18331 ms
Faster Regex Took 18421 ms
Faster Regex Took 18356 ms
Faster Regex Took 18297 ms
Faster Regex Took 18416 ms
Faster Regex Took 18338 ms
Faster Regex Took 18467 ms
Faster Regex Took 18326 ms
Faster Regex Took 18355 ms
Slow Regex Took 35748 ms
Slow Regex Took 35855 ms
Slow Regex Took 35924 ms
Slow Regex Took 35761 ms
Slow Regex Took 35764 ms
Slow Regex Took 35698 ms
Slow Regex Took 35646 ms
Slow Regex Took 35637 ms
Slow Regex Took 35871 ms
Slow Regex Took 35781 ms
答案 6 :(得分:0)
如果您不反对使用Apache Commons,那么您可以使用StringUtils
课程。
这意味着您不必为String.indexOf提供回报-1:
String parentStringValue = StringUtils.substringAfter(yourString, " ");