Pull to refresh

Comments 25

Никогда не говорите "никогда" :)
Даже среди стандартных классов немало примеров компараторов с вычитанием:

java.lang.Enum

        return self.ordinal - other.ordinal;

java.lang.String

        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;

java.time.Year

        return year - other.year;

Вычитание и лаконичней, и эффективней. Но, естественно, нужно осознавать диапазон значений.
Кстати, из той же серии. Типичная ошибка при реализации всякого рода lookup-таблиц:

    int hash = Math.abs(obj.hashCode());
    return table[hash % table.length];

В чём тут подвох? :)
В java HashMap table.lenght лежит в промежутке от 1 до 1<<30. Не будет тут 0)
Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.

Но знают далеко не многие. Я узнал от статического анализатора.
Это еще модуль вы добавили. Мы недавно словили такой баг, когда ключ одного из объектов перевели из int в String, а id % count заменили просто на id.hashCode() % count. При этом, поскольку это использовалось для распределения нагрузки между нодами, часть объектов просто не обрабатывалась и когда это обнаружили, не сразу стало понятно в чем дело =)
Integer.MIN_VALUE % (1 << x) для любого x равно 0
java.lang.Enum
Номер в перечислениях отрицательным быть не может.
java.lang.String
char неотрицательный.
java.time.Year
Ну тут да, если считать какие-нибудь астрономические или геологические периоды, то могут быть проблемки. «Ой».
Если элементы набора лежат в интервале [-m,+n], то результаты вычитания будут [-m-n,+m+n].

Так что, если в каком-то конкретном случае можно дать гарантию, что все элементы не превосходят по абсолютному значению MAX_VALUE/2, то использовать компаратор-вычитание можно.
Целая статья на хабре на такую тему. Хабр умирает? Похоже, что да.
Да вот не согласен. Вполне на мой взгляд хорошая техническая статья-заметка. Я например не знал и буквально недавно написал такой код. Да, понятно что происходит но я никогда в таком ключе не думал.
Тогда, по-моему автор должен был хотя бы разобраться, почему это происходит? Рассказать всем причину. Показать пути решения без изобретения велосипеда (например, если известно, что сравнение будет основываться на полях объекта, которые Comparable, то просто возвращать их сравнение через compare). Или собрать сборник подобных случаев-открытий автора. Тогда это будет похоже на статью. А так – чуть сократить и получится лаконичный твит =)

PS: а если все начнут постить свои небольшие открытие, то хабр превратится непонятно во что.
О причине рассказано в конце статьи.

Подборку таких случаев сделать было бы действительно круто. Но я это видел в основном в юзер-коде, до которого никому не было бы интереса. Реально интересно было бы скачать maven central и собрать по нему статистику, но нельзя (где-то они предостерегали, что будет бан). Так что от этой идеи я отказался и решил написать мини-статью. Я придерживаюсь мнения, что мини-статья — это необязательно плохо, а зависит от того, актуальна ли проблема.

Написать про Comparable? Тогда было бы слишком похоже на документацию, был бы смещен акцент, было бы скучно. Вы бы первый раскритиковали.
Удивлён, что никто ещё не написал про Integer.compare (Long, Character, Short, etc)
Под компаратором обычно подразумевают микросхему с аналоговыми входами, поэтому я думаю, что лучше назвать "… сравнения двух чисел на базе...". А то я было задумался как можно обойтись без вычитания, если простейшая модель работы операционного усилителя и является вычитанием с усилением K(u1 — u2)…
https://en.wikipedia.org/wiki/Comparator
Если бы тематикой поста была бы не Java, а схемотехника, вы были бы абсолютно правы.
Да, Java не заметил… Но всё равно компараторы не связаны с языками программирования.
Как интересно) И что им мешает быть связанными?
Ну нет такого в программировании. Среди чисто программистской братии многие удивятся, услышав компаратор. Это удел электроники (исторически так вышло). Спор ни о чем. Компаратор как электронное устройство создали намного раньше появления языка Java, поэтому по принципу старшинства (или большинства ассоциаций).
Тогда уж (раз в Java есть интерфейс Comparator) "… не делайте интерфейса Comparator на базе...".
  1. Если уж придираться к хрени, то интерфейс Comparator вообще нельзя сделать. Он уже давно готов. "… не делайте реализаций интерфейса Comparator на базе...".

  2. В java-сообществе слово "компаратор" имеет один главный смысл. Данный пост находится в единственном хабе — JAVA. Прошу заметить, даже не в программировании.

  3. Спор ни о чем.
    Спор о том, что вы пришли в одно сообщество со сленгом из другого.
Да, реализаций интерфейса. Будет лучше.
Когда я прочитал заголовок статьи среди списка, то на хаб не обратил внимания (где-то там мелко набрано Java).
Можете оценить по шкале от 1 до 100 масштаб трагедии?

Вы прочитали "компаратор" и настроились на железные аналоговые компараторы. Дальше идет фраза "на базе вычитания". Вопрос касается этой фразы. Какие ассоциации она у вас вызвала?
Трагедии никакой, то есть 1.
Ассоциации: а как ещё можно сделать?
Не совсем про компаратор, но еще интересный нежданчик может вызвать URL.equals()

Two URL objects are equal if they ...
«… reference equivalent hosts», а это может быть попыткой обращения к DNS.

Там же написано, что операция потенциально блокирующая, и что есть known issue про некорректность этого поведения с virtual hosts.

Во всяких Set'ах и Map'ах лучше использовать URI (с нормальным человеческим equals) или просто строки.
Sign up to leave a comment.

Articles