在Java中检查非空,而不是空白的字符串

par*_*tha 62 java string

我试图检查Java String是否不是null,不是空的而不是空格.

在我看来,这段代码应该完全适合这项工作.

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

根据文档,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;
}
Run Code Online (Sandbox Code Playgroud)

根据文件,Character.isWhitespace():

根据Java确定指定的字符是否为空白.当且仅当它满足以下条件之一时,字符才是Java空白字符:

  • 它是Unicode空格字符(SPACE_SEPARATOR,LINE_SEPARATORPARAGRAPH_SEPARATOR),但不也是非打破空间('\u00A0','\u2007','\u202F').
  • 它是'\t',U + 0009 HORIZONTAL TABULATION.
  • 它是'\n',U + 000A LINE FEED.
  • 它是'\u000B',U + 000B垂直制表.
  • 它是'\f',U + 000C FORM FEED.
  • 这是'\r',U + 000D CARRIAGE RETURN.
  • 它是'\u001C',U + 001C文件分离器.
  • 它是'\u001D',U + 001D GROUP SEPARATOR.
  • 它是'\u001E',U + 001E RECORD SEPARATOR.
  • 它是'\u001F',U + 001F UNIT SEPARATOR.

如果我没有弄错 - 或者可能是我只是没有正确阅读 - String.trim() 应该带走任何正在检查的角色Character.isWhiteSpace().所有人都认为在上面'\u0020'.

在这种情况下,更简单的isEmpty功能似乎涵盖了更长的覆盖的所有场景isBlank.

  1. 是否有一个字符串可以使测试用例中的行为isEmptyisBlank行为不同?
  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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和单元测试

@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) ;       

}
Run Code Online (Sandbox Code Playgroud)

更新:这是一个非常有趣的讨论 - 这就是为什么我喜欢Stack Overflow和这里的人们.顺便说一句,回到问题,我们得到:

  • 一个程序,显示所有字符将使行为不同.代码位于https://ideone.com/ELY5Wv.谢谢@Dukeling.
  • 选择标准的性能相关原因isBlank().谢谢@devconsole.
  • @nhahtdh的全面解释.谢了哥们.

nha*_*tdh 32

是否有一个字符串可以使测试用例中的行为isEmptyisBlank行为不同?

请注意,Character.isWhitespace可以识别Unicode字符并返回trueUnicode空白字符.

根据Java确定指定的字符是否为空白.当且仅当它满足以下条件之一时,字符才是Java空白字符:

  • 它是Unicode空格字符(SPACE_SEPARATOR,LINE_SEPARATORPARAGRAPH_SEPARATOR),但不也是非打破空间('\u00A0','\u2007','\u202F').

  • [...]

另一方面,trim()方法将修剪代码点低于U + 0020的所有控制字符和空格字符(U + 0020).

因此,在存在Unicode空白字符时,这两种方法的行为会有所不同.例如:"\u2008".或者当字符串包含不按Character.isWhitespace方法考虑空格的控制字符时.例如:"\002".

如果你要编写一个正则表达式来执行此操作(这比通过字符串循环并检查更慢):

  • isEmpty() 相当于 .matches("[\\x00-\\x20]*")
  • isBlank() 相当于 .matches("\\p{javaWhitespace}*")

(isEmpty()isBlank()方法都允许nullString引用,因此它不完全等同于正则表达式解决方案,但将它放在一边,它是等效的).

请注意\p{javaWhitespace},正如其名称所暗示的,是用于访问Character.isWhitespace方法定义的字符类的特定于Java的语法.

假设没有,是否还有其他考虑,因为我应该选择isBlank而不使用isEmpty

这取决于.但是,我认为上述部分的解释应该足以让您做出决定.总结差异:

  • isEmpty()如果字符串只包含U + 0020以下的控制字符1和空格字符(U + 0020),则会认为该字符串为空

  • isBlank如果字符串只包含Character.isWhitespace方法定义的空格字符,则会认为该字符串为空,其中包括Unicode空白字符.

1还有控制字符U+007F DELETE,不用trim()方法修剪.


Mar*_*oun 25

这两种标准方法的目的是区分这两种情况:

org.apache.common.lang.StringUtils.isBlank(" ")(将返回true).

org.apache.common.lang.StringUtils.isEmpty(" ")(将返回false).

您的自定义实现isEmpty()将返回true.


更新:

  • org.apache.common.lang.StringUtils.isEmpty() 用于查找String的长度是0还是null.

  • org.apache.common.lang.StringUtils.isBlank()向前迈进了一步.它不仅检查String是否为长度为0或null,还检查它是否只是一个空白字符串.

在你的情况,你修剪的字符串 isEmpty方法.现在唯一的区别是不会发生(你给它的情况" "),因为你正在修剪它(删除尾部空格 - 在这种情况下就像删除所有空格).

  • 我想每个人都很困惑.听着.Maroun Maroun的标准功能正确.但是,OP决定自己编写这个功能.请注意,通常,`isEmpty`将返回`false`,但现在测试是:`s.trim().length()> 0`.修剪`s`将删除所有前导和尾随字符串的空格.因此,``"`变成"""`.这个长度== 0.现在它将返回`false`! (6认同)

dev*_*ole 14

我会选择isBlank(),isEmpty()因为trim()创建一个新的String对象,以后必须进行垃圾回收.isBlank()另一方面,不会创建任何对象.

  • isBlank()在遇到第一个非空白字符时立即返回.唯一的问题是在末尾有一个非空白字符的长字符串,但是trim()也必须在内部迭代字符. (3认同)
  • @Dariusz对于那个问题,也不会是'isBlank`,对于带有尾随空格的非空字符串,它实际上会比`trim`更少迭代. (3认同)
  • @devconsole从OpenJDK 7 Update 6开始,在`String`中没有内部共享.你应该重新考虑你对"体面的Java实现"的定义. (2认同)