我应该使用哪种数据结构来保持按给定重量排序的元素?我需要在集合中添加元素,其中每个元素生成一个特定的权重,但这个权重不包含在元素本身内部(既不计算);它由元素之外的其他人计算。此外,不需要存储权重(但如果需要可以存储),它只是一个插入参数,可以将元素放在正确的位置。
我的具体用例是对音乐曲目进行排序。我有一个轨道列表和一个适用于每个轨道的规则列表。我遍历每个轨道,然后规则列表生成一个"得分"鉴于目前的轨道。我想将曲目添加到"集合"鉴于生成的分数,我可以选择得分最高的第一首曲目。
我无法看到在Java中使用哪种数据结构。我是否必须自己实施一个新的?我最好的猜测是一种堆数据结构,但我无法弄清楚哪一个具体。
编辑: 重量仅在开始时计算一次。我不能提供一个"比较器"因为它会比较曲目,我无法在" compareTo方法"上计算他们的分数。 该算法可能如下所示:
public Track determineNext() {
MyStructure<Track> trackScores;
for (Track track : tracks) {
int score = 0;
for (Rule rule : rules) {
score += rule.applyScoreOn(track);
}
trackScores.add(track, score);
}
return trackScores.first();
}
我希望你明白这一点。
答案 0 :(得分:1)
我认为PriorityQueue
正是您所需要的:
优先级队列的元素按其自然顺序排序,或者由队列构造时提供的比较器排序,具体取决于使用的构造函数。
在这种情况下,自然排序将按分数进行。容易。
关于你的观点:
我无法提供一个&#34;比较器&#34;因为它会比较曲目,我无法在&#34; compareTo方法&#34;上计算他们的分数。
这里的关键是您不能使用compareTo()
方法来计算分数。反之亦然。您在compareTo()
的实施中使用得分。
您可以通过以下几种方式实现此目标:
Track implements Comparable<Track>
,并实施compareTo(Track t)
比较您得分,所以得分更高 - &gt; &#34;较大的&#34;宾语。 PriorityQueue
将处理其余的事情。Comparator<Track>
基本相同的compareTo()
选项1。如果您可能稍后在程序中使用不同的条件进行排序,则选项2会更好,因为您不会仅仅按照分数对Track
进行排序。
理想情况下,对于这两个选项,您可以将分数存储在Track
内,因为分数只需要计算一次;但是,您必须确保在插入PriorityQueue
之前设置此分数。但这不应该成为一个问题。
或者,如果您知道得分不会随时间变化,可以在比较方法中即时计算得分;但是,如果必须进行大量的比较,这会随着时间的推移而变得有些昂贵。如果您知道得分不会改变,我不会推荐这个。
或者,如果Track
个对象对其得分一无所知(这是有道理的),您可以使用Map
Track
作为关键字并将得分作为关联的值Track
得分:
HashMap<Track, Integer> scoreMap = new HashMap<>();
for (Track track : tracks) { // Copied from question, slightly altered
int score = 0;
for (Rule rule : rules) {
score += rule.applyScoreOn(track);
}
scoreMap.put(track, Integer.valueOf(score));
现在您可以使用从此地图中提取分数的比较器
public class TrackComparator implements Comparator<Track> {
private final Map<Track, Integer> scores;
public TrackComparator(Map<Track, Integer> scores) {
this.scores = scores;
}
@Override
public int compare(Track t1, Track t2) {
// Check to see if tracks are in map if you didn't pre-fill map
// Get scores, compare, return
}
}
但有几点需要注意:
Map
通常要求您定义其他方法(hashCode()
除equals()
HashMap
以及TreeMap
的某种形式的比较器< / LI>
Track
个对象,我真的不能确定这是一个问题我不太确定Map
解决方案是最佳解决方案,但我认为远非最差,并且本身应该相当不错。
帮助解决内存问题的一个可能的变化是将Map
置于Comparator
内,并让比较器本身根据需要计算分数,如果轨道不是,则将它们添加到地图中。已经存在了。这取决于你是否关心某些分数被冻结&#34;比其他人晚。这可能会对性能造成不利影响,但这是一个很大的猜测。