Ранжирование элементов в наборе деревьев


Я знаю, что набор деревьев java не может иметь идентичных элементов, и поэтому я должен каким-то образом отличать один элемент от другого, даже если они имеют одинаковое "значение". Я хочу иметь возможность ранжировать элементы, и я замечаю интересное поведение.

TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>()
        {
            public int compare(Integer arg0, Integer arg1) 
            {
                if(arg0 > arg1)
                    return -1;
                return 1;
            }
        });

        set.add(40);
            set.add(20);
        set.add(30);
            set.add(20);

        for(Integer i:set)
        {
            System.out.println("Rank: "+(set.headSet(i,false).size()+1)+" Number: "+i);
        } 

И вот результат:

Rank: 1 Number: 40
Rank: 3 Number: 30
Rank: 5 Number: 20
Rank: 5 Number: 20

Вот что должна делать гарнитура:

Returns a view of the portion of this set whose elements are less than (or equal to, if inclusive is true) toElement. The returned set is backed by this set, so changes in the returned set are reflected in this set, and vice-versa. The returned set supports all optional set operations that this set supports. 

Я сортирую в порядке убывания, поэтому я думаю, что он должен делать наоборот. Первый элемент не имеет ничего большего, чем он, поэтому он возвращает 0, и затем я добавляю 1, чтобы получить его ранг. Второй элемент имеет одну вещь больше, чем он, поэтому я думаю, что он должен вернуть 1, добавив 1 делает 2. Это довольно странно. Я думаю, что совершаю простую ошибку. Мне также нужно выяснить, как справиться с двумя 20-ми. я хочу, чтобы их ранг был 3, но набор деревьев думает, что это разные числа. Я думаю, что могу использовать TreeMultiSet или какую-нибудь другую стороннюю библиотеку.

2 2

2 ответа:

Я полагаю, что могу использовать TreeMultiSet или какую-то другую стороннюю библиотеку.

Поскольку вы нарушаете одну из основных характеристик набора, я бы сказал, что вы не должны использовать Set или TreeSet, по крайней мере напрямую. Варианты:
  • используйте List (и держите его отсортированным с коллекциями.sort () и коллекции.binarySearch ())
  • используйте IdentityHashMap и просто используйте значение как ключ, сопоставленный самому себе
  • используйте карту деревьев и сопоставьте значение с # событий (извлечение в список и сортировка по мере необходимости)
  • используйте стороннюю библиотеку (Bag или MultiSet)
  • реализуйте свой собственный пакет / multiset
Поскольку я не знаю больше о контексте программирования, трудно предложить конкретное решение, но, надеюсь, это вызовет некоторые другие идеи для рассмотрения.

Два 20 являются проблемой, потому что ваша реализация сравнения нарушает контракт:

Конструктор должен гарантировать SGN(х.метод compareto(г)) == -сгн(г.метод compareto(X)) для всех X и y.

Если x=20 и y=20, это неверно в вашей имплементации: 1 == -(1)

Эту проблему можно устранить, вернув 0, если arg0.равно (arg1).

Примечание: Для объектов класса Integer необходимо использовать "equals" вместо"==".