Отношение эквивалентности и естественный порядок на классе в Java
Я очень хорошо понял разницу между интерфейсами Comparable и Comparator, и как таковой порядок, навязанный ими.
Кроме того, мне ясно, почему CompareTo должно соответствовать методу equals. Из документов Oracle,
Настоятельно рекомендуется (хотя и не обязательно), чтобы естественные порядки соответствовали равным. Это так, потому что отсортированные наборы (и отсортированные карты) без явных компараторов ведут себя "странно", когда они используются с элементами (или ключами), чье естественное упорядочение несовместимо с равенством. В частности, такой отсортированный набор (или отсортированная карта) нарушает общий контракт для набора (или карты), который определяется в терминах метода equals.
Например, если добавить два ключа
a
а такжеb
такой, что(!a.equals(b) && a.compareTo(b) == 0)
для отсортированного набора, в котором не используется явный компаратор, вторая операция добавления возвращает значение false (и размер отсортированного набора не увеличивается), поскольку a и b эквивалентны с точки зрения отсортированного набора.
Тем не менее, я не могу очистить себя от пункта (ниже),
Для математически наклоненного отношения, которое определяет естественный порядок в данном классе C, имеет вид:
{(x, y) such that x.compareTo(y) <= 0}.
Коэффициент для этого общего заказа:
{(x, y) such that x.compareTo(y) == 0}.
Это следует непосредственно из договора на
compareTo
что частное отношение является отношением эквивалентности на C, и что естественное упорядочение является полным порядком на C. Когда мы говорим, что естественное упорядочение класса согласуется с равенствами, мы имеем в виду, что частное для естественного упорядочения является отношением эквивалентности, определяемым классequals(Object)
метод:{(x, y) such that x.equals(y)}.
Что автор пытается предложить здесь? Может кто-нибудь объяснить на простом примере.
3 ответа
В основном это говорит о том, что в соответствии с равными означает, что набор (x
, y
) пары для которых x.compareTo(y) == 0
является true
идентично набору (x
, y
) пары для которых x.equals(y)
является true
,
Это ничем не отличается от здравого смысла в соответствии с равными в первом абзаце. Это просто выражено определением в формальной алгебраической форме. Я уверен, что кто-то решил, что было бы забавно добавить это в документы, но я не уверен, что это имеет какую-либо практическую полезность для программистов.
Допустим, вы создаете этот глупый класс
public class A implements Comparable<A> {
private int value;
public A(int value){
this.value = value }
public boolean equals(Object obj){
if (obj instanceof A)
return this.value = ((A)obj).value;
else return false;
}
public int compareTo(A another){
return 0;
}
}
Затем вы создаете два экземпляра:
A a1 = new A(3);
A a2 = new A(4);
SortedSet<A> set = new TreeSet<A>();
set.add(a1);
set.add(a2);
SortedSet принимает a1, но не принимает a2, потому что a1.equals(a2) == false, но a2.compareTo(a2) == 0; Помните, что в наборе для определения все элементы отличаются друг от друга (это похоже на математическую концепцию множества).
Это все математика! (х, у) означает "х относится к у"
Отношение эквивалентности - это отношение к совокупности элементов (в данном случае экземпляров класса C), которое является отражающим, симметричным и переходным.
отражающее означает: что каждый элемент относится к самому себе, симметричные средства: если a относится к b, то b относится к переходному средству: если a относится к b, а b относится к c, то a относится к c.
таким образом, отношение отношения x.compareTo (y) == 0, таким образом, является отношением эквивалентности, поскольку для каждого экземпляра c в C: c.compareTo (c) предполагается равным нулю, для каждого экземпляра c1, c2 из C: если c1.comparTo (c2) == 0, тогда c2.compareTo (c1) также должно быть равно нулю. И для всех c1, c2, c3, где c1.compareTo (c2) равно нулю, а c2.compareTo (c3) равно нулю, тогда c1.compareTo (c3) также должно быть равно нулю.
Общий порядок - это отношение, которое является транзитивным (см. Выше), антисимметричным (снова см. Выше, но теперь инвертированным, поскольку оно является анти-) и итоговым, следовательно, CompareTo должно отражать общий порядок: если a.compareTo (b) равен <= 0 и b.compareTo (c) <= 0, тогда a.compareTo (c) должно быть <= 0, если a.compareTo (b) <= 0, тогда b.compareTo (a) должно быть>= 0
total означает, что либо a.compareTo (b) <= 0, либо b.compareTo (a) <= 0, значение total означает, что любой элемент можно сравнить с другим элементом, поэтому все элементы можно упорядочить, чтобы порядок был полным.
частное происходит от a.compareTo (b) <= 0 и b.compareTo (a) <= 0, следовательно, a.compareTo (b) == 0
Я надеюсь, что это немного более объяснительно, чем оригинал...