Почему реализация Java PriorityQueue использует Comparator<? super E> а не просто Comparator<E>

Исходный код Java PriorityQueue, определенный в jdk8, использует компаратор, определенный следующим образом.

    /**
     * The comparator, or null if priority queue uses elements'
     * natural ordering.
     */
    private final Comparator<? super E> comparator;

Исходный код здесь (строка 108)

Почему необходимо использовать тип, который превосходит E, а не просто E.

Другими словами, почему бы не определить компаратор, как показано ниже:

    private final Comparator<E> comparator;

Какова мотивация этой дополнительной абстракции?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Почему бы и нет.

Учитывая компаратор, который может сравнивать любые 2 объекта CharSequence (CharSequence — это интерфейс; String, StringBuilder и некоторые другие вещи реализуют его), то… это так же хорошо, когда вам нужно сравнивать только строки. Все строки также являются CharSequences, поэтому компаратор, который может сказать вам для любых двух объектов charsequence, какой из них «приходит первым», может отлично выполнять эту работу.

Дженерики инвариантны по умолчанию, поэтому, если у вас есть PriorityQueue<String>, и он работает так, как вы хотите, он будет выглядеть как Comparator<E>, что означает Comparator<String>, а Comparator<CharSequence> будет не совместимы с этим. Подобно передаче String методу, которому нужен объект Integer, он просто не компилируется.

Следовательно, <? super E>, чтобы вы могу передали Comparator<CharSequence>.

Встречается, конечно, не часто, но так "правильнее". Я уверен, вы будете удивлены, если у вас есть компаратор CharSequences, лежащий рядом, и вы не можете использовать его для питания PriorityQueue<String>.

Спасибо за быстрый ответ, это имеет смысл! Почему бы и нет, я бы только сказал, что при чтении кода с ? super E, а не просто E. Хотя я согласен, что это того стоит из-за упомянутых вами преимуществ.

Youness 18.03.2022 23:28

Другие вопросы по теме