Мне нужно сохранить коллекцию объектов, отсортированных по атрибуту «рейтинг», даже если я получу больше объектов, которые уже находятся в коллекции - PullRequest
0 голосов
/ 23 мая 2018

Я программирую алгоритм, который будет получать строки из базы данных, эти строки будут определены в объекте, который имеет атрибуты, которые их идентифицируют, и атрибут «ранжирование».Я должен использовать коллекцию (или найти способ), чтобы сохранить все эти объекты, отсортированные по значению ранжирования. ОДНАКО, если я получу другой объект, равный другому, уже находящемуся в коллекции (за исключением ранжирования), мне нужно обновитьранжирование значений (суммирование рангов обоих объектов) и сохранение сортировки коллекции.

Я думал о TreeSet, но я никак не могу обновить значение, которое не находится в корне ...

Хорошо, скажем, моя коллекция выглядит так:

(name='Federer', id='131', ranking='3000')
(name='Nadal', id='234', ranking='2500')
(name='Del Potro', id='180', ranking='1800')

Если я получу это:

(name='Nadal', id='234', ranking='1000')

Коллекция должна закончиться так:

(name='Nadal', id='234', ranking='3500')
(name='Federer', id='131', ranking='3000')
(name='Del Potro', id='180', ranking='1800')

Большое спасибо заранее.

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

Я провел некоторые эксперименты с TreeSet и TreeMap, но не смог найти ничего интересного для вашей ситуации.В зависимости от того, как часто вы добавляете элементы в коллекцию, может быть лучше просто использовать HashMap и сортировать его при необходимости.

Чтобы он был более эффективным, вы могли бы даже отслеживать некоторые boolean флаг, обозначающий, что HashMap находится в отсортированном состоянии (если Map уже отсортировано, то нет необходимости сортировать его снова, если ничего не изменилось!).

var map = new HashMap<Element, Integer>();

map.put(new Element("Federer", 131), 3000);
map.put(new Element("Nadal", 234), 2500);
map.put(new Element("Del Potro", 180), 1800);

map.forEach((k, v) -> System.out.println(k + "=" + v));

System.out.println();

map.merge(new Element("Nadal", 234), 1000, Math::addExact);

map.entrySet()
   .stream()
   .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
   .forEach(System.out::println);

Вывод:

[Federer, 131]=3000
[Nadal, 234]=2500
[Del Potro, 180]=1800

[Nadal, 234]=3500
[Federer, 131]=3000
[Del Potro, 180]=1800

Примечание : я определил класс Element с полями name и id и использую эти поля при переопределении Object#equals и Object#hashCode.

0 голосов
/ 23 мая 2018

Вы можете сохранить текущую карту ранжирования по идентификатору и использовать ее в качестве основы для очереди приоритетов для сортировки элементов:

Map<Integer, Integer> rankingById = new HashMap<>();
Queue<Integer> idsByRanking = new PriorityQueue<>(
        Comparator.comparing(rankingById::get).reversed());

void addItem(Item item) {
    Integer id = item.getId();
    idsByRanking.remove(id);
    rankingById.merge(id, item.getRanking(), Integer::sum);
    idsByRanking.add(id);
}

Необходимо удалить элемент перед обновлением рейтинга, чтобы онмогут быть вставлены в правильном положении.См. Также: Обновление Java PriorityQueue, когда его элементы меняют приоритет

0 голосов
/ 23 мая 2018

Вы сказали в комментариях, что ваш учитель рекомендовал деревья, но я не понимаю, как вы могли бы использовать для этого классы TreeSet или TreeMap (по крайней мере, так, как они есть).

  • TreeMap сохраняетупорядочение по ключам (которые в вашем случае являются идентификаторами), в то время как вы хотите упорядочить записи на основе их ранжирования.
  • TreeSet, с другой стороны, нуждается в некотором свойстве, которое помогло бы ему сравнить две записи друг с другом, чтобы сохранить только те, которые являются уникальными (так как это набор).Если вы хотите сравнить на основе ранжирования, то, если два ранжирования равны, древовидная структура будет думать, что эти две записи эквивалентны (что может быть не так).Если вы сравниваете на основе идентификаторов, то они будут отсортированы по идентификаторам, а не по рейтингу.

Я думаю, что проще всего будет хранить записи в HashMap.И затем, когда вам нужен отсортированный список, вы можете вызвать values() на хэш-карте, отсортировать их и затем отобразить.Вы также упомянули, что количество записей не превысит 300, поэтому сортировка должна быть очень быстрой в любом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...