我需要保留按 "ranking" 属性排序的对象集合,即使我获得了集合中已有的更多对象



我正在编写一个算法,它将从数据库中接收行,这些行将在具有标识它们的属性和"排名"属性的对象中定义。我必须使用集合(或找到一种方法(来保持所有这些对象按排名值排序,但是如果我收到另一个与集合中已有的其他对象相等的对象(排名除外(,我需要更新排名值(将两个对象的排名相加(并保持集合排序。

我在考虑一个树集,但我无法更新不在根上的值......

好吧,假设我的收藏是这样的:

(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')

提前非常感谢。

我已经对TreeSetTreeMap进行了一些实验,但找不到适合您情况的任何有趣内容。 根据向集合添加元素的频率,最好只使用HashMap并在必要时对其进行排序。

为了提高效率,您甚至可以跟踪一些表示HashMap处于排序状态的boolean标志(如果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

注意:我定义了一个具有nameid字段的类Element,并在覆盖Object#equalsObject#hashCode时使用这些字段。

你在评论中说你的老师推荐了树,但我看不出你如何使用 TreeSet 或 TreeMap 类(至少它们是这样(。

  • 树状图按键(在您的情况下是 id(保持排序, 而您希望根据排名对条目进行排序。
  • 另一方面,TreeSet需要一些可以帮助它的属性 将两个条目相互比较,以仅保留以下条目 是唯一的(因为它是一个集合(。如果要根据 排名,那么如果两个排名相等,树集会认为 两个条目是等效的(这可能不是真的(。如果您比较 基于 ID,然后将根据 ID 而不是 ID 进行排序 排名。

我认为最简单的方法是将条目存储在HashMap中。然后,当您需要排序列表时,您可以在哈希图上调用values(),对它们进行排序,然后显示。您还提到条目数量不会超过 300,因此无论如何排序应该非常快。

您可以保留按 ID 排名的实时地图,并将其用作优先级队列的基础,以保持项目排序:

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 元素更改优先级时更新其优先级

最新更新