Исходный код 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;
Какова мотивация этой дополнительной абстракции?
Почему бы и нет.
Учитывая компаратор, который может сравнивать любые 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. Хотя я согласен, что это того стоит из-за упомянутых вами преимуществ.