среда, 1 августа 2012 г.

collections: comparable-comparator

java.lang.Comparable:
    "The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C."
    "It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method."
    "It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact."

    Литература:
    The Java™ Programming Language, Fourth Edition. By Ken Arnold, James Gosling, David Holmes (стр 463)
    Шилд. "Метод compareTo()" для строк (стр 402-404)
    Шилд. "Сравнение метода equals() и оператора ==" для строк (стр 402)
    Шилд. "Компараторы" (стр 511-514)


    "Сортирующие" коллекции (TreeSet, TreeMap) каким-то "магическим" образом "знают как" правильно упорядочить строки:
import java.util.Set;
import java.util.TreeSet;

public class Example {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("C");
        set.add("A");
        set.add("B");
        System.out.println(set);
    }
}
>> [A, B, C]

    И числа:
import java.util.Set;
import java.util.TreeSet;

public class Example {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(3);
        set.add(1);
        set.add(2);
        System.out.println(set);
    }
}
>> [1, 2, 3]

    Так пусть же упорядочит и экземпляры нашего класса!
public class User {
    private int age;
    private String name;

    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {return age;}

    public String getName() {return name;}

    public String toString() {return "User[" + age + ", '" + name + "']";}
}
import java.util.Set;
import java.util.TreeSet;

public class _2_ComparableUserExample {
    public static void main(String[] args) {
        Set<User> set = new TreeSet<>();
        set.add(new User(3, "B"));
        set.add(new User(1, "C"));
        set.add(new User(2, "A"));
        System.out.println(set);
    }
}
>> Exception in thread "main" java.lang.ClassCastException: User cannot be cast to java.lang.Comparable
    Упс ...

0
>> 0


0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

0
>> 0

    Вопросы для самостоятельной проработки:
1) в каком порядке выведет " abc", " ABC", "abc", "ABC"?
2) нормально ли будет работать TreeSet/TreeMap с экземплярами разных классов?