63

Java String がnull空でも空白でもないかどうかを確認しようとしています。

私の考えでは、このコードは十分に機能していたはずです。

public static boolean isEmpty(String s) {
    if ((s != null) && (s.trim().length() > 0))
        return false;
    else
        return true;
}

ドキュメントに従って、次のString.trim()ように動作するはずです:

先頭と末尾の空白を省略して、文字列のコピーを返します。

このStringオブジェクトが空の文字シーケンスを表す場合、またはこのオブジェクトによって表される文字シーケンスの最初と最後の文字の両方が(スペース文字)Stringより大きいコードを持つ場合、このオブジェクトへの参照が返されます。'\u0020'String

ただし、apache/commons/lang/StringUtils.java少し異なります。

public static boolean isBlank(String str) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
        return true;
    }
    for (int i = 0; i < strLen; i++) {
        if ((Character.isWhitespace(str.charAt(i)) == false)) {
            return false;
        }
    }
    return true;
}

ドキュメントによると、次のCharacter.isWhitespace()とおりです。

Javaに従って、指定された文字が空白かどうかを判断します。次の基準のいずれかを満たす場合に限り、その文字は Java 空白文字です。

  • これは Unicode スペース文字 ( SPACE_SEPARATORLINE_SEPARATOR、またはPARAGRAPH_SEPARATOR) ですが、非改行スペース ( '\u00A0''\u2007''\u202F') ではありません。
  • '\t'U+0009 HORIZONTAL TABULATIONです。
  • '\n'、U+000A LINE FEEDです。
  • '\u000B'、U+000B VERTICAL TABULATIONです。
  • '\f'、U+000C FORM FEEDです。
  • '\r'、U+000D CARRIAGE RETURNです。
  • '\u001C'、U+001C FILE SEPARATORです。
  • '\u001D'、U+001D GROUP SEPARATORです。
  • '\u001E'、U+001E RECORD SEPARATORです。
  • '\u001F'、U+001F UNIT SEPARATORです。

私が間違っていない場合、または正しく読んでいない可能性がある場合String.trim() は、 によってチェックされている文字を削除する必要がありますCharacter.isWhiteSpace()。それらはすべて上にあるように見えます'\u0020'

この場合、単純なisEmpty関数は、より長い関数がカバーするすべてのシナリオをカバーしているように見えますisBlank

  1. テスト ケースでisEmptyとの動作を変える文字列はありますか?isBlank
  2. 何もないと仮定すると、選択isBlankして使用しないための考慮事項は他にありますisEmptyか?

実際にテストを実行することに興味がある人のために、メソッドと単体テストを次に示します。

public class StringUtil {

    public static boolean isEmpty(String s) {
        if ((s != null) && (s.trim().length() > 0))
            return false;
        else
            return true;
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }
}

そして単体テスト

@Test
public void test() {
    
    String s = null; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;
    
    s = ""; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)); 
    
    s = " "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;
    
    s = "   "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;
    
    s = "   a     "; 
    assertTrue(StringUtil.isEmpty(s)==false) ;    
    assertTrue(StringUtil.isBlank(s)==false) ;       
    
}

更新: とても興味深い議論でした。これが私が Stack Overflow とここにいる人々が好きな理由です。ところで、質問に戻ると、次の結果が得られました。

  • どのキャラクターが異なる振る舞いをするかを示すプログラム。コードはhttps://ideone.com/ELY5Wvにあります。ありがとう@Dukeling。
  • 標準を選択するパフォーマンス関連の理由isBlank()。@devconsole に感謝します。
  • @nhahtdh による包括的な説明。ありがとう。
4

8 に答える 8

32

テスト ケースでisEmptyとの動作を変える文字列はありますか?isBlank

は Unicode 文字を認識し、Unicode 空白文字Character.isWhitespaceを返すことができることに注意してください。true

Javaに従って、指定された文字が空白かどうかを判断します。次の基準のいずれかを満たす場合に限り、その文字は Java 空白文字です。

  • これは Unicode スペース文字 ( SPACE_SEPARATORLINE_SEPARATOR、またはPARAGRAPH_SEPARATOR) ですが、非改行スペース ( '\u00A0''\u2007''\u202F') ではありません。

  • [...]

一方、trim()メソッドは、コード ポイントが U+0020 およびスペース文字 (U+0020) より下にあるすべての制御文字を削除します。

したがって、Unicode 空白文字が存在する場合、2 つのメソッドの動作は異なります。例: "\u2008". または、メソッドによって空白と見なされない制御文字が文字列に含まれているCharacter.isWhitespace場合。例: "\002".

これを行うために正規表現を作成する場合 (文字列をループしてチェックするよりも遅くなります):

  • isEmpty()と同等です.matches("[\\x00-\\x20]*")
  • isBlank()と同等です.matches("\\p{javaWhitespace}*")

( isEmpty()andisBlank()メソッドは両方ともnull文字列参照を許可するため、正規表現ソリューションと完全に同等ではありませんが、それは別として、同等です)。

\p{javaWhitespace}は、その名前が示すように、メソッドによって定義された文字クラスにアクセスするための Java 固有の構文であることに注意してくださいCharacter.isWhitespace

何もないと仮定すると、選択isBlankして使用しないための考慮事項は他にありますisEmptyか?

場合によります。ただし、上記の部分の説明で十分に判断できると思います。違いを要約するには:

  • isEmpty()U+0020 の1 つ下の制御文字と空白文字 (U+0020)のみが含まれている場合、文字列は空であると見なされます。

  • isBlankメソッドで定義された空白文字のみが含まれている場合、文字列は空であると見なされますCharacter.isWhitespace。これには Unicode 空白文字が含まれます。

1メソッドU+007F DELETEによってトリミングされない制御文字も にあります。trim()

于 2013-05-06T08:48:25.937 に答える
25

2 つの標準メソッドの目的は、この 2 つのケースを区別することです。

org.apache.common.lang.StringUtils.isBlank(" ")( trueを返します)。

org.apache.common.lang.StringUtils.isEmpty(" ")( falseを返します)。

のカスタム実装はtrueisEmpty()を返します。


アップデート:

  • org.apache.common.lang.StringUtils.isEmpty()String の長さが 0 か null かを調べるために使用されます。

  • org.apache.common.lang.StringUtils.isBlank()一歩前進します。String が長さ 0 または null であるかどうかをチェックするだけでなく、それが単なる空白文字列であるかどうかもチェックします。

あなたの場合、メソッドで文字列をトリミングしています isEmpty。現在発生する可能性のある唯一の違いは、それをトリミング" "しているため発生しません (指定した場合) (末尾の空白を削除する - この場合は、すべてのスペースを削除するようなものです)。

于 2013-05-06T08:27:21.040 に答える
14

後でガベージ コレクションする必要がある新しい String オブジェクトを作成するため、選択isBlank()します。一方、オブジェクトは作成されません。isEmpty()trim()isBlank()

于 2013-05-06T08:33:40.170 に答える
4

Annotatinos@NotEmpty@NotNull. メソッドの本来の目的から検証の問題を分離できるため、Bean Validation はクールです。

于 2013-05-06T08:38:24.387 に答える
1

ネストされた三項演算子を使用してこれを実現できないのはなぜですか。サンプル コードを調べてください。 public static void main(String[] args) { String s = null; String s1=""; String s2="hello"; System.out.println(" 1 "+check(s)); System.out.println(" 2 "+check(s1)); System.out.println(" 3 "+check(s2)); } public static boolean check(String data) { return (data==null?false:(data.isEmpty()?false:true)); }

出力は次のとおりです

1 偽 2 偽 3 真

ここで、最初の 2 つのシナリオは false (つまり、null と空) を返し、3 番目のシナリオは true を返します。

于 2015-07-08T12:25:17.430 に答える
0
<% 
System.out.println(request.getParameter("userName")+"*");

if (request.getParameter("userName").trim().length() == 0 | request.getParameter("userName") == null) { %>
<jsp:forward page="HandleIt.jsp" />
<% }
 else { %>
Hello ${param.userName}
<%} %>
于 2014-08-07T10:22:22.813 に答える
0

Java 8 では、フィルタリングで Optional 機能を使用することもできました。文字列が空白かどうかを確認するために、コードは追加ライブラリのない純粋な Java SE です。次のコードは isBlank() の実装を示しています。

String.trim() の動作

!Optional.ofNullable(tocheck).filter(e -> e != null && e.trim().length() > 0).isPresent()

StringUtils.isBlank() の動作

Optional.ofNullable(toCheck)
    .filter(e -> 
        {
            int strLen;
            if (str == null || (strLen = str.length()) == 0) {
                return true;
            }
            for (int i = 0; i < strLen; i++) {
                if ((Character.isWhitespace(str.charAt(i)) == false)) {
                    return false;
                }
            }
            return true;

        })
    .isPresent()
于 2016-08-31T20:56:36.960 に答える