Должен ли я использовать string.isEmpty () или «» .equals (string)?


171

Название в основном говорит обо всем. Я обычно тестирую это вместе с a string == null, так что я не очень обеспокоен нулевым тестом. Какой я должен использовать?

String s = /* whatever */;
...
if (s == null || "".equals(s))
{
    // handle some edge case here
}

или

if (s == null || s.isEmpty())
{
    // handle some edge case here
}

На этой ноте - isEmpty()даже делает что-нибудь кроме return this.equals("");или return this.length() == 0;?


26
Имейте в виду, что isEmpty()это только Java 6+.
— ColinD

1
Вы можете создать вспомогательный метод Util.String.hasValue (String s), который проверяет наличие пустых значений, пустоты и пробелов для обработки всех случаев.
— Cloudanger

5
@ColinD Вероятно, не проблема - J2SE 5.0 завершил период окончания срока службы некоторое время назад.
— Том Хотин - тэклайн

1
Еще одна вещь, которую нужно учитывать, это "" .equals () принимает Object в качестве аргумента, поэтому вы не получите ошибку компилятора, если тип аргумента изменится со String на что-то другое, в лучшую или худшую сторону.
— Пол Джексон

Ответы:


251

Основное преимущество "".equals(s)заключается в том, что вам не нужна проверка на нулевое значение ( equalsпроверит ее аргумент и вернет значение, falseесли оно равно нулю), которая, по-видимому, вас не беспокоит Если вы не беспокоитесь о том, sчтобы быть нулевым (или иным образом проверяете это), я бы определенно использовал s.isEmpty(); он показывает именно то, что вы проверяете, вас волнует, sявляется ли он пустым или нет , равно ли оно пустой строке


29
Спасибо за объяснение. Теперь я знаю, почему стоит отдавать предпочтение "" .equals (str) перед str.equals ("")! Мне всегда было интересно, почему другие используют это так часто, но не принимали во внимание нулевые значения. Отлично :-)
— Питер Випперманн

10
ИМХО проверка нуля все еще необходима в приведенных выше примерах, поскольку мы предполагаем, что условие должно быть истинным для значения null. s == ноль || "" .equals (s)
— mkorpela

5
@ Master.Aurora нет, если getValue()возвращено значение NULL, вы получите toString()
— исключение

12
@RenniePet Это не значит, что в этом есть какая-то магия. Если sноль, вы не можете вызывать методы для него - это ноль. ""никогда не будет нулевым, поэтому вы можете безопасно вызывать методы для него и equals()обрабатывать случай, когда его аргумент равен нулю
— Майкл Мрозек

5
Замечание по производительности: isEmpty()проверяет внутреннюю длину частного массива, тогда как equals(Object anObject)делает гораздо больше (например, проверяет instanceof). По производительности, isEmpty()как правило, быстрее.
— Тьюринг85

82

String.equals("")на самом деле немного медленнее, чем просто isEmpty()звонок. Строки хранят переменную count, инициализированную в конструкторе, поскольку строки являются неизменяемыми.

isEmpty() сравнивает переменную count с 0, в то время как equals проверит тип, длину строки, а затем перебирает строку для сравнения, если размеры совпадают.

Таким образом, чтобы ответить на ваш вопрос, на isEmpty()самом деле будет делать гораздо меньше! и это хорошо.


3
Я думаю, что в этом случае разница не применяется; никогда не будет итерации по строкам для сравнения, потому что размеры не будут совпадать (если строка на самом деле не пуста, а затем нет символов для итерации)
— Майкл Мрозек

2
Верно, но при равенстве вы сначала выполняете проверку ссылок, чтобы увидеть, являются ли они одним и тем же объектом, затем instanceof, затем приведением к String, проверкой длины и, наконец, итерацией. Если бы обе строки были пустыми, то это была бы простая проверка ссылок.
— Дэвид Янг

исходный код для класса String доступен java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
— Дэвид Янг

1
@ Дэвид мертвая ссылка; вот живой docjar.com/html/api/java/lang/String.java.html#1011
— Мэтт Болл,

17

Одной вещью, которую вы могли бы рассмотреть помимо других упомянутых проблем, является то, что isEmpty()было введено в 1.6, поэтому, если вы используете его, вы не сможете запустить код на Java 1.5 или ниже.


4
Это определенно не беспокоит меня.
— Мэтт Болл

1
Также этот ответ сейчас 6 лет назад. Я надеюсь, что больше никто не будет использовать что-то древнее, такое как Java 1.5.
— Миша Наследов

1
На самом деле есть много вещей, которые могут сломаться при обновлении Java-версии. Это менее критично для фонового приложения, работающего на большом сервере, но имеет значение для клиентских приложений. Графические библиотеки и стратегии сборки мусора часто подвергаются серьезному и незначительному обновлению Java. Кроме того, клиентское программное обеспечение может работать в различных операционных системах и иногда с ограниченной памятью, что означает, что у вас часто не будет бюджета / ресурсов для тестирования всего. - Да, у меня есть клиенты, которые все еще придерживаются Java 5 в 2017 году.
— bvdb


2

Это не имеет большого значения. "".equals(str)более понятно на мой взгляд.

isEmpty()возвращается count == 0;


47
Я бы сказал, str.isEmpty()что гораздо яснее, чем "".equals(str). Это читается как то, что вы проверяете. Вопрос мнения, хотя, я думаю.
— ColinD

7
Я думаю, что некоторые люди предпочитают делать "" .equals (str), чтобы избежать NPE. Мне лично это не нравится, потому что я бы предпочел, чтобы строка не была нулевой.
— CoolBeans

2

Я написал класс тестера, который может проверить производительность:

public class Tester
{
    public static void main(String[] args)
    {
        String text = "";

        int loopCount = 10000000;
        long startTime, endTime, duration1, duration2;

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.equals("");
        }
        endTime = System.nanoTime();
        duration1 = endTime - startTime;
        System.out.println(".equals(\"\") duration " +": \t" + duration1);

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.isEmpty();
        }
        endTime = System.nanoTime();
        duration2 = endTime - startTime;
        System.out.println(".isEmpty() duration "+": \t\t" + duration2);

        System.out.println("isEmpty() to equals(\"\") ratio: " + ((float)duration2 / (float)duration1));
    }
}

Я обнаружил, что использование .isEmpty () занимает примерно половину времени .equals ("").


Это недействительный микробенчмарк. Я настоятельно рекомендую использовать Caliper или аналогичный специализированный инструмент для тестирования. stackoverflow.com/q/504103/139010
— Мэтт Болл

Спасибо за чаевые! Когда у меня будет немного свободного времени, я поэкспериментирую с некоторыми микро-бенчмаркингами и обновлю свой ответ.
— conapart3
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.