Строка a, b: if (a.equals (b)), if (Objects.equals (a, b)) или if (a..hashCode () == b.hashCode ())?

Alexander Savin спросил: 28 марта 2018 в 04:13 в: java

Что лучше для строк (String a; String b;): if(Objects.equals(a, b)) или if(a.hashCode()==b.hashCode())?

Я использовал if(Objects.equals(a, b)) для API Android > = 19 и if(a.hashCode()==b.hashCode()) для Android API < 19, но я не помню, почему ...


5 ответов

RaffoSorr ответил: 28 марта 2018 в 04:59

Как вы можете прочитать, проверив документацию по классу Object здесь,

Нет необходимости, чтобы, если два объекта были неравны в соответствии с методом equals (java.lang.Object), тогда вызывается Метод hashCode для каждого из двух объектов должен давать разные целочисленные результаты. Однако программист должен знать, что создание различных целочисленных результатов для неравных объектов может повысить производительность хеш-таблиц.

Это означает, что даже если a.hashCode () == b.hashCode ( ) имеет значение true, это не обязательно означает, что a.equals (b) имеет значение true.

Для сравнения объектов всегда следует полагаться на метод equals. Это верно для любого типа объекта, если только у вас нет особых потребностей, и не только для строк.

Редактировать: как указано в комментариях,

hashCode может возвращать одно и то же для двух совершенно разных типов объектов

Alexander Savin ответил: 28 марта 2018 в 04:23
А как насчет ссылки на документацию / проверки Android API? Где я могу прочитать о разнице для API < 19?
RaffoSorr ответил: 28 марта 2018 в 04:25
Методы equals и hashCode определены в классе Object начиная с самой первой версии языка Java. Я не могу представить, почему он должен отличаться для API < 19 и API > = 19. У вас не должно возникнуть проблем при использовании equals в API < 19 :)
RaffoSorr ответил: 28 марта 2018 в 04:29
Вы должны использовать другие методы (или вообще другой код) только в том случае, если вы хотите получить доступ к новым функциям API, но также хотите поддерживать более старые версии Android. Android использует Java, а equals и hashCode доступны начиная с Java 1 и начиная с Android API 1, поэтому оба должны быть доступны: вы говорите не о новой функции языка Java или новой функции API Android, а о базовой особенность Java. Надеюсь, это более понятно.
Gabe Sechan ответил: 28 марта 2018 в 04:56
Более того, hashCode может возвращать одно и то же для двух совершенно разных типов объектов. Я могу иметь Integer и String, которые хэшируют к одному значению. Если вы хотите проверить равенство, всегда используйте равно.
Alexander Savin ответил: 28 марта 2018 в 05:33
@Raffolox Я отредактировал вопрос и опубликовал ответ ниже
raydex ответил: 28 марта 2018 в 04:16

Более правдоподобно (как с точки зрения семантики, так и с точки зрения соглашения) использование Equals. Не нужно предпринимать дополнительные действия. Как вы можете в исходном коде равных можно сравнивать объекты одинаковы.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}
Alexander Savin ответил: 28 марта 2018 в 05:35
Я отредактировал вопрос и опубликую свой ответ ниже
Francis Nduba Numbi ответил: 28 марта 2018 в 11:11

String имеет свою собственную версию equals () и equalsIgnoreCase (). использовать их,

Alexander Savin ответил: 28 марта 2018 в 05:20

Я использовал if(Objects.equals(a, b)) вместо if(a.equals(b)), потому что инспекция

'String.equals ()', вызванная в интернационализированном контексте, сообщает о любом вызове equals (), equalsIgnoreCase (), compareTo () или compareToIgnoreCase () для объектов String , Такие вызовы обычно некорректны в не интернационализированной среде.

Я использовал if(a.hashCode()==b.hashCode()) для API < 19 вместо if(Objects.equals(a, b)), потому что для проверки

для вызова требуется уровень API 19 (текущий минимум - 14): java.util.Objects # equals

Andy Turner ответил: 28 марта 2018 в 05:32
Знаете ли вы, как реализован Objects.equals(a, b)? В этом нет ничего волшебного: если аргументы не равны нулю (а это не может быть, если вы вместо них планируете вызывать hashCode), это то же самое, что вызывать a.equals(b).
Andy Turner ответил: 28 марта 2018 в 04:55

В Javadoc говорится о Object.hashCode:

Этот метод поддерживается для использования хеш-таблиц, таких как предоставляемые HashMap.

Если вы не создаете хеш-таблицу, использование hashCode почти наверняка не является правильным методом для использования.


Вы на самом деле не описали что вы пытаетесь сделать, но Objects.equals(a, b) и a.hashCode() == b.hashCode() не являются заменяемыми.

Например, Objects.equals("AA", "Ab") имеет значение false, но "AA".hashCode() == "Ab".hashCode() верно.

Alexander Savin ответил: 28 марта 2018 в 05:35
Я отредактировал вопрос и опубликую свой ответ ниже