Проверка не пустой, а не пустой строки в Java
Я пытаюсь проверить, не является ли строка Java не 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 тогда и только тогда, когда он удовлетворяет одному из следующих критериев:
- Это символ пробела в Юникоде (
SPACE_SEPARATOR
, LINE_SEPARATOR
или PARAGRAPH_SEPARATOR
), но также не является неразрывным пробелом ('\u00A0'
, '\u2007'
, '\u202F'
). - Это
'\t'
, U + 0009 ГОРИЗОНТАЛЬНАЯ ТАБУЛЯЦИЯ. - Это
'\n'
, U + 000A LINE FEED. - Это
'\u000B'
, U + 000B ВЕРТИКАЛЬНАЯ ТАБУЛЯЦИЯ. - Это
'\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
.
- Есть ли строка, которая приведет к тому, что
isEmpty
и isBlank
будут вести себя по-другому в тестовом примере?
- Предполагая, что их нет, есть ли какое-либо другое соображение, из-за которого я должен выбрать
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) ;
}
Обновление: Это была действительно интересная дискуссия, и именно поэтому я люблю Qaru и людей здесь. Кстати, вернувшись к вопросу, мы получили:
- Программа, показывающая, что все символы будут вести себя по-другому. Код находится в https://ideone.com/ELY5Wv. Спасибо @Dukeling.
- Связанная с производительностью причина выбора стандарта
isBlank()
. Спасибо @devconsole.
- Полное описание @nhahtdh. Спасибо друг.
Ответы
Ответ 1
Есть ли строка, в которой поведение isEmpty
и isBlank
будет вести себя по-другому в тестовом случае?
Обратите внимание, что Character.isWhitespace
может распознавать символы Unicode и возвращать true
для символов Unicode пробелов.
Определяет, является ли указанный символ пробелом в соответствии с Java. Символ является символом пробела Java тогда и только тогда, когда он удовлетворяет одному из следующих критериев:
-
Это символ пробела в Юникоде (SPACE_SEPARATOR
, LINE_SEPARATOR
или PARAGRAPH_SEPARATOR
), но также не является неразрывным ('\u00A0'
, '\u2007'
, '\u202F'
).
-
[...]
С другой стороны, метод trim()
обрезает все управляющие символы, чьи кодовые точки ниже U + 0020 и пробельный символ (U + 0020).
Следовательно, эти два метода будут вести себя по-разному в присутствии символа пробела Unicode. Например: "\u2008"
. Или, когда строка содержит управляющие символы, которые не учитывают пробелы методом Character.isWhitespace
. Например: "\002"
.
Если вы должны были написать регулярное выражение для этого (что медленнее, чем выполнение цикла через строку и проверка):
-
isEmpty()
будет эквивалентен .matches("[\\x00-\\x20]*")
-
isBlank()
будет эквивалентен .matches("\\p{javaWhitespace}*")
(Методы isEmpty()
и isBlank()
допускают null
ссылку на String, поэтому он не совсем эквивалентен решению регулярного выражения, но отбрасывает его в сторону, это эквивалентно).
Обратите внимание, что \p{javaWhitespace}
, как следует из его имени, является синтаксисом, специфичным для Java, для доступа к классу символов, определенному методом Character.isWhitespace
.
Предполагая, что их нет, есть ли какое-либо другое соображение, из-за которого я должен выбрать isBlank
и не использовать isEmpty
?
Это зависит. Тем не менее, я думаю, что объяснение в части выше должно быть достаточным для вас. Подводя итог разнице:
-
isEmpty()
будет считать, что строка пуста, если она содержит только управляющие символы 1 ниже U + 0020 и символ пробела (U + 0020)
-
isBlank
будет считать, что строка пуста, если она содержит только пробельные символы, определенные методом Character.isWhitespace
, который включает символы пробела Unicode.
1 Существует также управляющий символ в U+007F DELETE
, который не обрезается методом trim()
.
Ответ 2
Цель двух стандартных методов состоит в том, чтобы различать эти два случая:
org.apache.common.lang.StringUtils.isBlank(" ")
(вернет true).
org.apache.common.lang.StringUtils.isEmpty(" ")
(вернет false).
Ваша пользовательская реализация isEmpty()
вернет значение true.
UPDATE:
-
org.apache.common.lang.StringUtils.isEmpty()
используется для определения того, является ли строка длиной 0 или нулевой.
-
org.apache.common.lang.StringUtils.isBlank()
делает шаг вперед. Он не только проверяет, является ли String длиной 0 или нулевым, но также проверяет, является ли это только строка пробела.
В вашем случае вы обрезаете строку в своем методе isEmpty
. Единственное различие, которое может произойти сейчас, не может произойти (случай, который вы даете ему " "
), потому что вы обрезка его (удаление конечного пробела - которое находится в этот случай похож на удаление всех пробелов).
Ответ 3
Я бы выбрал isBlank()
над isEmpty()
, потому что trim()
создает новый объект String, который должен быть собран позже. isBlank()
, с другой стороны, не создает никаких объектов.
Ответ 4
Вы можете взглянуть на JSR 303 Bean Validation, в котором содержатся Annotatinos @NotEmpty
и @NotNull
. Bean Валидация классная, потому что вы можете отделить вопросы проверки от первоначального намерения метода.
Ответ 5
Почему вы не можете просто использовать вложенный тернарный оператор для достижения этого. Пожалуйста, ознакомьтесь с примером кода
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 false 2 false 3 true
здесь 1-й 2 сценария возвращает false (i.e null и empty), а третий сценарий возвращает true
Ответ 6
<%
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}
<%} %>
Ответ 7
Этот простой код будет достаточно:
public static boolean isNullOrEmpty(String str) {
return str == null || str.trim().equals("");
}
И модульные тесты:
@Test
public void testIsNullOrEmpty() {
assertEquals(true, AcdsUtils.isNullOrEmpty(""));
assertEquals(true, AcdsUtils.isNullOrEmpty((String) null));
assertEquals(false, AcdsUtils.isNullOrEmpty("lol "));
assertEquals(false, AcdsUtils.isNullOrEmpty("HallO"));
}
Ответ 8
С помощью Java 8 вы также можете использовать опцию "Дополнительно" с фильтрацией. Чтобы проверить, является ли строка пустой, код является чистым 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()