我正在编写一个算法,它将从数据库中接收行,这些行将在具有标识它们的属性和"排名"属性的对象中定义。我必须使用集合(或找到一种方法(来保持所有这些对象按排名值排序,但是如果我收到另一个与集合中已有的其他对象相等的对象(排名除外(,我需要更新排名值(将两个对象的排名相加(并保持集合排序。
我在考虑一个树集,但我无法更新不在根上的值......
好吧,假设我的收藏是这样的:
(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')
提前非常感谢。
我已经对TreeSet
和TreeMap
进行了一些实验,但找不到适合您情况的任何有趣内容。 根据向集合添加元素的频率,最好只使用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
注意:我定义了一个具有name
和id
字段的类Element
,并在覆盖Object#equals
和Object#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 元素更改优先级时更新其优先级