假设有一个类似" world "
的字符串。此字符串的开头和结尾只有空格。 trim()
比replace()
快吗?
我曾经使用过一次替换,我的导师说不要使用它,因为trim()
可能更快。
如果没有,trim()
比replace()
有什么优势?
答案 0 :(得分:8)
如果我们查看source code中的方法:
public String replace(CharSequence target, CharSequence replacement) {
String tgtStr = target.toString();
String replStr = replacement.toString();
int j = indexOf(tgtStr);
if (j < 0) {
return this;
}
int tgtLen = tgtStr.length();
int tgtLen1 = Math.max(tgtLen, 1);
int thisLen = length();
int newLenHint = thisLen - tgtLen + replStr.length();
if (newLenHint < 0) {
throw new OutOfMemoryError();
}
StringBuilder sb = new StringBuilder(newLenHint);
int i = 0;
do {
sb.append(this, i, j).append(replStr);
i = j + tgtLen;
} while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
return sb.append(this, i, thisLen).toString()
}
对比trim()
:
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
如您所见,replace()
调用了多个其他方法并在整个String
中进行迭代,而trim()
只是在String
的开头和结尾进行迭代,直到字符不是空格。因此,就尝试仅 删除单词前后的空白而言,trim()
效率更高。
我们可以对此进行一些基准测试:
public static void main(String[] args) {
long testStartTime = System.nanoTime();;
trimTest();
long trimTestTime = System.nanoTime() - testStartTime;
testStartTime = System.nanoTime();
replaceTest();
long replaceTime = System.nanoTime() - testStartTime;
System.out.println("Time for trim(): " + trimTestTime);
System.out.println("Time for replace(): " + replaceTime);
}
public static void trimTest() {
for(int i = 0; i < 1000000; i ++) {
new String(" string ").trim();
}
}
public static void replaceTest() {
for(int i = 0; i < 1000000; i ++) {
new String(" string ").replace(" ", "");
}
}
输出:
Time for trim(): 53303903
Time for replace(): 485536597
//432,232,694 difference
答案 1 :(得分:4)
trim()
肯定是更快键入,是的。它不带任何参数。
了解您要去哪里做什么也更快。您试图修剪字符串,而不是用空字符串替换其包含的所有空格,从其他上下文中得知,字符串的开头和结尾都只有空格< / em>。
无论您如何看,它的确要快得多。不要使试图阅读您的代码的人的生活复杂化。在大多数情况下,是几个月之后,或者至少是您不讨厌的人。
答案 2 :(得分:3)
假设编写Java库代码的人做得很好 1 ,则可以假设一个特殊目的的方法(如trim()
)将同样快,甚至可能更快比通用方法(例如replace(...)
)做同样的事情。
两个原因:
如果专用方法较慢,则可以将其实现重写为对通用方法的等效调用,从而使性能在大多数情况下等效。有能力的程序员会这样做,因为它可以减少维护成本。
在特殊用途方法中,可能会进行一些优化,而这些优化不适用于一般用途。
在这种情况下,我们知道trim()
仅需要 来查看字符串的开头和结尾...而replace(...)
需要查看字符串中的所有字符。 (我们可以从相应方法的描述中推断出这一点。)
如果我们假设“胜任力”,那么我们可以推断出开发人员将进行分析,而未实现trim()
欠佳的 2 ;也就是说,他们不会编码trim()
来检查所有字符。
使用通用方法而不是通用方法还有另一个原因。它使您的代码更简单,更易于阅读,并且更易于检查正确性。这可能比性能更重要。
这显然适用于trim()
与replace(...)
的情况。
1-在这种情况下,我们可以。有很多人在看这段代码,很多人会大声抱怨性能过高的问题。
2-不幸的是,它并不总是那么简单。需要针对“典型”行为优化库方法,但是还需要避免在边缘情况下的病理表现。并非总是都能做到这两者。
答案 3 :(得分:1)
修剪将修剪外面的字符,直到它们不是空格为止。我相信它们会修剪空间,制表符和换行符。
替换将扫描整个字符串(因此,它可能是一个句子),并将内部的“”替换为“”,本质上将它们压缩在一起。
尽管它们有不同的用例,但明显的1是清理用户输入,而另一个是在找到匹配项的情况下更新字符串。
也就是说,运行时间:替换将在N次后运行,因为它将查找所有匹配的字符。修剪将以O(N)运行,但最有可能在每个末端减少几个字符。
修剪的想法我想是人们会输入的内容,但是在提交表单之前不小心按了空格,本质上是试图保存字段“ Foo”而不是“ Foo”
答案 4 :(得分:0)
s.trim()
缩短了String s
。这意味着不必将字符从索引移到另一个。它从s.toCharArray()[0]
的第一个字符(String
)开始,并逐个字符地缩短String
字符,直到出现第一个非空白字符。其作用与缩短String
的末尾相同。因此,它将压缩String
。如果String
没有开头和结尾的空格,则trim
将在检查第一个和最后一个字符后准备就绪。
对于" world ".trim()
,需要执行两个步骤:一个步骤是删除第一个索引中的第一个前导空白,而第二个步骤删除最后一个索引中的最后一个空白。
" world ".replace(" ", "")
将至少需要n = " world ".length()
个步骤。它必须检查每个字符是否必须替换。但是,如果考虑到String.replace(...)
的实现需要编译Pattern
,构建Matcher
然后替换所有匹配的区域,与缩短{{ 1}}。
我们还必须考虑String
不能代替空格,而只能代替" world ".replace(" ", "")
String
。由于" "
使用String replace(CharSequence target, CharSequence replacement)
编译目标,因此我们不能使用字符类 \ s 。为了更准确,我们必须将Pattern.LITERAL
与" world ".trim()
进行比较。仍然不一样,因为" world ".replaceAll("\\s", "")
中每个String trim()
的{{1}}中的空白都定义为c <= ' '
。
总结:c
应该更快-特别是对于长字符串
方法的工作方式说明基于Java 8中s.toCharArray()
的实现。但是实现可以更改。
但是问题应该是:您打算对字符串做什么?您要修剪还是要替换某些字符?根据它使用相应的方法。