我有String str
,我想从中提取不包含可能前缀"abc"
的子字符串。
首先想到的解决方案是:
if (str.startsWith("abc"))
return str.substring("abc".length());
return str;
我的问题是:
使用split
以及"abc"
前缀的正则表达式是否有“更干净”的方法?
如果是,它的效率是否低于上述方法(因为它会“遍历”字符串)?
如果是,是否有更好的方法(“更好的方式”=清洁有效的解决方案)?
请注意,"abc"
前缀可能会出现在字符串的其他位置,不应删除。
由于
答案 0 :(得分:37)
比上面的代码更短的是这一行:
return str.replaceFirst("^abc", "");
但就性能而言,我猜两个代码之间不会有任何实质性差异。一个使用正则表达式,一个不使用正则表达式,但搜索和子串。
答案 1 :(得分:5)
将String.replaceFirst
与^abc
一起使用(以匹配前导abc
)
"abcdef".replaceFirst("^abc", "") // => "def"
"123456".replaceFirst("^abc", "") // => "123456"
"123abc456".replaceFirst("^abc", "") // => "123abc456"
答案 2 :(得分:1)
String#split
可以做到这一点,但它并不是更好的解决方案。实际上它很模糊,我不建议将它用于此目的。startsWith
。String#startsWith
就是为此设计的。您可以轻松衡量代码运行所需的时间。在这里你可以做什么:
创建一个大循环,在其中你可以将它的计数器附加到一些虚拟字符串,以模拟你想要检查的字符串,然后尝试startsWith
一次,replaceAll
之后:
for(int i = 0;i<900000;i++) {
StringBuilder sb = new StringBuilder("abc");
sb.append(i);
if(sb.toString().startsWith("abc")) { ... }
}
long time = System.currentTimeMillis() - start;
System.out.println(time); //Prints ~130
for(int i = 0;i<900000;i++){
StringBuilder sb = new StringBuilder("abc");
sb.append(i);
sb.toString().replaceAll("^abc", "");
}
long time = System.currentTimeMillis() - start;
System.out.println(time); //Prints ~730
答案 3 :(得分:1)
试试这个
str = str.replaceAll("^abc", "");
答案 4 :(得分:1)
一个无正则表达式的解决方案(我之所以需要这个,因为我正在移除的字符串是可配置的并且包含反斜杠,需要转义才能在正则表达式中直接使用):
Apache Commons Lang StringUtils.removeStart(str, remove)
将使用remove
和str
从String.startsWith
开头删除String.substring
。
该方法的source code提供了丰富的信息:
public static String removeStart(final String str, final String remove) {
if (isEmpty(str) || isEmpty(remove)) {
return str;
}
if (str.startsWith(remove)){
return str.substring(remove.length());
}
return str;
}
答案 5 :(得分:-2)
就效率而言,您可以使用StringBuilder
,其中您对一个字符串有多个操作,例如substring,查找索引,然后是子字符串等等。
在清洁/效率方面,可以使用StringUtils (Apache Commons Lang)
。
希望它有所帮助。