Если мы посмотрим, как это делает TreeMap
, это может дать нам представление о том, как мы можем это реализовать:
По своей природе (будучи двоичным деревом), TreeMap
необходимо сравнить ключи, так что они правильно помещаются в двоичное дерево, но класс TreeMap
требует ключ универсального типа, который не должен реализовывать Compareable
.Это объявление:
public class TreeMap<K,V> extends ...
Конструктор TreeMap
не может иметь аргументов или аргумент Comparator
:
public TreeMap() {
comparator = null;
}
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
И у него есть функция compare
, которую он используетвнутренне:
final int compare(Object k1, Object k2) {
return comparator == null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
Эта функция compare
объясняет, как она работает: сначала она пытается использовать предоставленный объект comparator
для сравнения двух объектов.Если он недоступен, он предполагает, что объекты сравнимы, и пытается сравнить их, используя их реализацию Comparable
, приводя их к экземплярам Comparable
.Если они на самом деле не реализуют Comparable
, выдается ClassCastException
, и в этом случае TreeMap
работает неправильно.
Итак, вывод заключается в том, что есть способреализовать коллекцию, которая может сравнивать любые два объекта, предоставляя либо внешние, либо внутренние функции сравнения, но тогда у обобщений должны быть меньшие ограничения, и при неправильном использовании могут возникать ошибки.