Почему метод добавления TreeSet ведет себя по-разному в разных JRE?

Я пытаюсь добавить объекты класса Employee в TreeSet. Я не реализую интерфейс Comparable или Comparator. Но код метода add ведет себя по-разному в разных системах. Почему так? Фрагмент кода ниже: -

import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {
public static void main(String[] args) {

    Set<Employee> set = new TreeSet<Employee>();
    set.add(new Employee());
//  set.add(new Employee());
//  set.add(new Employee());
 }
}

В текущей системе (Win 10), независимо от того, пишу ли я метод set.add() один или три раза. Он всегда генерирует ClassCastException во время выполнения. Но говоря об этом вопросе - Почему TreeSet выдает ClassCastException Пользователь там написал, что он не получает исключения, когда использует метод добавления только один раз.

Кроме того, в другой системе (Win 7) вчера я пытался добавить объект 3 раза, трижды вызывая метод set, и ClassCastException не было!! Размер набора остается только 1, поэтому оказалось, что несколько объектов просто НЕ добавляются в набор.

Так что же может быть причиной разного поведения метода add?


person shanti    schedule 17.06.2016    source источник
comment
Во всяком случае, это будет версия JRE, а не версия Windows.   -  person shmosel    schedule 17.06.2016
comment
@shmosel да, так что я думаю, что разные версии окон также будут иметь разные JRE.   -  person shanti    schedule 17.06.2016
comment
Они могут или они не могут. Почему бы тебе не проверить?   -  person shmosel    schedule 17.06.2016
comment
@TimBiegeleisen Да, я просто скопировал это из своей системы. Win 10 работает под управлением Java 8, но проект работает на версии 1.6.   -  person shanti    schedule 17.06.2016
comment
Если вы уже знаете причину ошибки, а именно не реализуете Comparable или предоставление пользовательского компаратора во время построения, то зачем задавать вопрос? Обратите внимание, что сравнение для упорядочивания на самом деле не нужно делать до добавления второго элемента. Возможно, есть небольшое изменение в реализации между Java 6 и Java 8. В любом случае вы не должны использовать отсортированный набор без какого-либо понятия о наличии компаратора.   -  person Tim Biegeleisen    schedule 17.06.2016
comment
@TimBiegeleisen, потому что мне интересно узнать внутреннее поведение   -  person shanti    schedule 17.06.2016


Ответы (1)


TreeSet.add() делегирует TreeMap.put(), поведение которого в Java 6 и Java 8 отличается.

Java 6:

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        // TBD:
        // 5045147: (coll) Adding null to an empty TreeSet should
        // throw NullPointerException
        //
        // compare(key, key); // type check
        root = new Entry<K,V>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    ...

Java 8:

public V put(K key, V value) {
    Entry<K,V> t = root;
    if (t == null) {
        compare(key, key); // type (and possibly null) check

        root = new Entry<>(key, value, null);
        size = 1;
        modCount++;
        return null;
    }
    ...

Как видите, в более ранней версии строка compare() по какой-то причине была закомментирована, но в более поздней версии она была добавлена ​​обратно. Отсюда и исключение, которое вы видите для первого элемента.

См. также здесь: Почему TreeSet можно использовать в качестве ключа для TreeMap в jdk 1.6?

person shmosel    schedule 17.06.2016
comment
Интересно. Спасибо за это. Позвольте мне прочитать детали реализации классов, чтобы иметь больше ясности. - person shanti; 17.06.2016
comment
Большое спасибо за этот ответ. Я быстро просмотрел реализацию класса TreeMap, и вы совершенно правы. В Java 6 метод сравнения закомментирован, но раскомментирован в Java 7 и 8. Таким образом, в Java 7 и 8 он будет генерировать ClassCastException, но не в 6. - person shanti; 18.06.2016