1. 概要

メソッドString.trim()は、末尾と先頭の空白を削除します。 ただし、L-TrimまたはR-Trimを実行するだけのサポートはありません。

このチュートリアルでは、これを実装する方法をいくつか見ていきます。 最後に、それらのパフォーマンスを比較します。

2. 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正規表現の使用

もう1つのオプションは、 String.replaceAll()と正規表現を使用することです。

String ltrim = src.replaceAll("^\\s+", "");
String rtrim = src.replaceAll("\\s+$", "");

(\\ s +)は、1つまたは複数の空白文字に一致する正規表現です。 正規表現の最初と最後のキャレット(^)と($)は、行の最初と最後に一致します。

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 メソッドを利用して、空白を削除できます。

そのために、最初にcommons-lang3依存関係を追加しましょう。

<dependency> 
    <groupId>org.apache.commons</groupId> 
    <artifactId>commons-lang3</artifactId> 
    <version>3.12.0</version> 
</dependency>

ドキュメントに従って、空白を取り除くためにnullを使用します。

String ltrim = StringUtils.stripStart(src, null);
String rtrim = StringUtils.stripEnd(src, null);

6. グアバ

最後に、 Guava CharMatcher#trimLeadingFromメソッドと#trimTrailingFromメソッドを使用して同じ結果を取得します。

ここでも、適切なMaven依存関係を追加しましょう。今回は、そのguavaです。

<dependency> 
    <groupId>com.google.guava</groupId> 
    <artifactId>guava</artifactId> 
    <version>31.0.1-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. ベンチマークの設定

ベンチマークの初期構成では、5つのフォークとナノ秒単位の平均時間計算時間を使用しました。

@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

第四に、Apache Commons:

@Benchmark
public boolean apacheCommonsStringUtils() {
    String ltrim = StringUtils.stripStart(src, " ");
    String rtrim = StringUtils.stripEnd(src, " ");
    return checkStrings(ltrim, rtrim);
}

7.6. グアバ

そして最後に、Guavaを使用しましょう。

@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 loop、Apache Commons、Guavaのようです。

8. 結論

このチュートリアルでは、Stringの最初と最後の空白文字を削除するいくつかの異なる方法を確認しました。

この結果を得るために、 while loop、 String.replaceAll()、 Pattern.matcher()。replaceAll()、ApacheCommonsとGuavaを使用しました。

いつものように、コードはGitHubから入手できます。