在Java中检查非空,非空string

我正在试图检查一个Javastring是不是null ,不是空的,而不是空白。

在我看来,这个代码应该已经很适合这份工作了。

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

根据文档, String.trim()应该这样工作:

返回string的副本,省略前导和尾随空白。

如果这个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_SEPARATORPARAGRAPH_SEPARATOR ),但也不是一个非'\u00A0'空间( '\u00A0''\u2007''\u202F' )。
  • 这是'\t' ,U + 0009水平制表。
  • 这是'\n' ,U + 000A线路馈送。
  • U + 000B垂直制表'\u000B''\u000B'
  • 这是'\f' ,U + 000C FORM FEED。
  • 它是'\r' ,U + 000D装运返回。
  • U + 001C FILE SEPARATOR是'\u001C'
  • U + 001D GROUP SEPARATOR是'\u001D'
  • U + 001E RECORD SEPARATOR是'\u001E'
  • U + 001F UNIT SEPARATOR是'\u001F'

如果我没有弄错 – 或者可能是我只是没有正确地读取它 – String.trim()应该带走由Character.isWhiteSpace()检查的任何字符。 他们都'\u0020''\u0020'

在这种情况下,简单的是isBlank函数似乎覆盖了更长的isBlank所覆盖的所有场景。

  1. 有没有一个string,将使isEmptyisBlank在testing用例中performance不同?
  2. 假设没有,有没有其他的考虑,因为我应该selectisBlank而不是使用isEmpty

对于那些对实际运行testing感兴趣的人,下面是方法和unit testing。

 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; } } 

和unit testing

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

更新:这是一个非常有趣的讨论 – 这就是为什么我喜欢堆栈溢出和这里的人。 顺便说一句,回到这个问题,我们得到了:

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

有没有一个string,将使isEmptyisBlank在testing用例中performance不同?

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

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

  • 它是一个Unicode空格字符( SPACE_SEPARATORLINE_SEPARATORPARAGRAPH_SEPARATOR ),但也不是一个非'\u00A0'空间( '\u00A0''\u2007''\u202F' )。

  • [...]

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

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

如果你要写一个正则expression式来做这件事(比通过string和检查循环要慢):

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

isEmpty()isBlank()方法都允许nullstring引用,所以它不完全等同于正则expression式解决scheme,但放在一边,它是等价的)。

请注意, \p{javaWhitespace}顾名思义是访问由Character.isWhitespace方法定义的字符类的Java专用语法。

假设没有,有没有其他的考虑,因为我应该selectisBlank而不是使用isEmpty

这取决于。 不过,我认为上面的解释应该足以让你自己决定。 总结一下:

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

  • 如果string仅包含由Character.isWhitespace方法(包括Unicode空白字符)定义的空白字符,则isBlank会认为该string为空。

1 U+007F DELETE还有一个控制字符,它不会被trim()方法trim()

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

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或空值,还检查它是否只是一个空白string。

你的情况,你正在修剪你的 isEmpty方法中的string。 现在唯一不同的情况是不能发生的(你给它的情况" " ),因为你正在修剪它(删除尾部的空白 – 在这种情况下,就像删除所有空格一样)。

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

您可以看看JSR 303 Bean Validation(包含Annotatinos @NotEmpty@NotNull 。 Bean Validation是很酷的,因为你可以从方法的原始意图中分离validation问题。

为什么不能简单地使用一个嵌套的三元运算符来实现这一点。请查看示例代码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)); } 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真

这里前两个场景返回false(即空和空),第三个场景返回true

 <% 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} <%} %> 

这个简单的代码就足够了:

 public static boolean isNullOrEmpty(String str) { return str == null || str.trim().equals(""); } 

而unit testing:

 @Test public void testIsNullOrEmpty() { assertEquals(true, AcdsUtils.isNullOrEmpty("")); assertEquals(true, AcdsUtils.isNullOrEmpty((String) null)); assertEquals(false, AcdsUtils.isNullOrEmpty("lol ")); assertEquals(false, AcdsUtils.isNullOrEmpty("HallO")); } 

使用Java 8,您还可以使用可选function进行筛选。 为了检查一个string是否为空,代码是纯粹的Java SE,没有额外的库。 下面的代码illustre是一个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()