1.概述
方法String.trim()删除尾随和前导空格。但是,不支持仅执行L-Trim或R-Trim。
在本教程中,我们将看到一些实现此目标的方法。最后,我们将比较它们的性能。
2. while循环
最简单的解决方案是使用几个while循环遍历字符串。
对于L-Trim,我们将从左至右读取字符串,直到遇到非空白字符为止:
int i = 0;
while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
i++;
}
String ltrim = s.substring(i);
ltrim是从第一个非空白字符开始的子字符串。
对于R-Trim,我们将从右到左读取字符串,直到遇到非空白字符:
int i = s.length()-1;
while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
i--;
}
String rtrim = s.substring(0,i+1);
rtrim是一个子字符串,从第一个非空白字符的开头开始到结尾。
3. String.replaceAll使用正则表达式
另一个选择是使用String.replaceAll()和一个正则表达式:
String ltrim = src.replaceAll("^\\s+", "");
String rtrim = src.replaceAll("\\s+$", "");
(\\ s +)是与一个或多个空格字符匹配的正则表达式。正则表达式开头和结尾的插入符号(^)和($)与行的开头和结尾匹配。
4. Pattern.compile()和.matcher()
我们也可以使用java.util.regex.Pattern重用正则表达式:
private static Pattern LTRIM = Pattern.compile("^\\s+");
private static Pattern RTRIM = Pattern.compile("\\s+$");
String ltrim = LTRIM.matcher(s).replaceAll("");
String rtim = RTRIM.matcher(s).replaceAll("");
5. Apache Commons
此外,我们可以利用Apache Commons StringUtils#stripStart和#stripEnd方法来删除空格。
为此,我们首先添加的 公地lang3 依赖性:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
根据文档,我们使用null来去除空格:
String ltrim = StringUtils.stripStart(src, null);
String rtrim = StringUtils.stripEnd(src, null);
6.Guava
最后,我们将利用Guava CharMatcher#trimLeadingFrom和#trimTrailingFrom 方法获得相同的结果。
再次,让我们添加适当的Maven依赖项,这次是guava:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-jre</version>
</dependency>
在Guava中,它与Apache Commons中的实现方法非常相似,只是使用了更具针对性的方法:
String ltrim = CharMatcher.whitespace().trimLeadingFrom(s);
String rtrim = CharMatcher.whitespace().trimTrailingFrom(s);
7.性能比较
让我们看看这些方法的性能。像往常一样,我们将使用开源框架Java Microbenchmark Harness(JMH)来比较不同的替代方案(以纳秒为单位)。
7.1。基准设定
对于基准测试的初始配置,我们使用了五个分叉和平均时间计算时间(以纳秒为单位):
@Fork(5)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
在设置方法中,我们正在初始化原始消息字段和生成的字符串以与以下内容进行比较:
@Setup
public void setup() {
src = " White spaces left and right ";
ltrimResult = "White spaces left and right ";
rtrimResult = " White spaces left and right";
}
所有基准测试首先删除左空格,然后删除右空格,最后将结果与预期字符串进行比较。
7.2。while循环
对于我们的第一个基准测试,让我们使用while循环方法:
@Benchmark
public boolean whileCharacters() {
String ltrim = whileLtrim(src);
String rtrim = whileRtrim(src);
return checkStrings(ltrim, rtrim);
}
7.3。具有正则表达式的String.replaceAll()
然后,让我们尝试String.replaceAll():
@Benchmark
public boolean replaceAllRegularExpression() {
String ltrim = src.replaceAll("^\\s+", "");
String rtrim = src.replaceAll("\\s+$", "");
return checkStrings(ltrim, rtrim);
}
7.4。Pattern.compile()。matches()
之后是Pattern.compile()。matches():
@Benchmark
public boolean patternMatchesLTtrimRTrim() {
String ltrim = patternLtrim(src);
String rtrim = patternRtrim(src);
return checkStrings(ltrim, rtrim);
}
7.5。阿帕奇共享区
第四,Apache Commons:
@Benchmark
public boolean apacheCommonsStringUtils() {
String ltrim = StringUtils.stripStart(src, " ");
String rtrim = StringUtils.stripEnd(src, " ");
return checkStrings(ltrim, rtrim);
}
7.6。番石榴
最后,让我们使用番石榴:
@Benchmark
public boolean guavaCharMatcher() {
String ltrim = CharMatcher.whitespace().trimLeadingFrom(src);
String rtrim = CharMatcher.whitespace().trimTrailingFrom(src);
return checkStrings(ltrim, rtrim);
}
7.7。结果分析
我们应该得到一些类似于以下内容的结果:
# Run complete. Total time: 00:16:57
Benchmark Mode Cnt Score Error Units
LTrimRTrim.apacheCommonsStringUtils avgt 100 108,718 ± 4,503 ns/op
LTrimRTrim.guavaCharMatcher avgt 100 113,601 ± 5,563 ns/op
LTrimRTrim.patternMatchesLTtrimRTrim avgt 100 850,085 ± 17,578 ns/op
LTrimRTrim.replaceAllRegularExpression avgt 100 1046,660 ± 7,151 ns/op
LTrimRTrim.whileCharacters avgt 100 110,379 ± 1,032 ns/op
看来我们的赢家是while循环,Apache Commons和Guava!
8.结论
在本教程中,我们研究了在String的开头和结尾处删除空格字符的几种不同方法。
我们使用while循环,String.replaceAll(), Pattern.matcher()。replaceAll(), Apache Commons和Guava来获得此结果。
与往常一样,该代码可在GitHub上获得。