简体   繁体   English

数据结构按值排序

[英]Data-structure sorted by value

I am trying to store a score for a large about of players. 我正在尝试为大部分玩家存储一个分数。 So I will need a map that is sorted based on the value, but because of the amount of players it's inefficient to sort it each time I retrieve it. 因此,我需要根据值排序的地图,但是由于玩家数量众多,每次检索时对它进行排序的效率都很低。 I would also like the ability to find a players rank in the map. 我还希望能够在地图上找到一名球员。 It would be very similar to the score datatype in redis. 这将与redis中的score数据类型非常相似。 Something like: 就像是:

    ScoreMap<String, Integer> scores = new ScoreMap<String, Integer>();

    scores.put("Bill", 2);
    scores.put("Tom", 6);
    scores.put("Jim", 3);
    scores.put("Jake", 3);


    System.out.println("Rank = " + scores.getRank("Bill"));

    System.out.println();
    System.out.println("All:");
    for (Entry<String, Integer> entry : scores.entrySet()) {
        System.out.println(entry.getKey() + " => " + entry.getValue());
    }

    System.out.println();
    System.out.println("Rank Range:");
    for (Entry<String, Integer> entry : scores.entryRankRange(0, 2)) {
        System.out.println(entry.getKey() + " => " + entry.getValue());
    }

    System.out.println();
    System.out.println("Score Range:");
    for (Entry<String, Integer> entry : scores.entryScoreRange(2, 3)) {
        System.out.println(entry.getKey() + " => " + entry.getValue());
    }

This would return 这将返回

    Rank = 3

    All:
    Tom => 6
    Jake => 3
    Jim => 3
    Bill => 2

    Rank Range:
    Tom => 6
    Jake => 3
    Jim => 3

    Score Range:
    Jake => 3
    Jim => 3
    Bill => 2

I know this is kinda specific and I will probably have to make a custom data-structure. 我知道这是特定的,我可能必须创建一个自定义的数据结构。 But a point in the right direction would be much appreciated. 但是,朝着正确方向的观点将不胜感激。 :) :)

Simplest way to do this would be to use a Set (namely, TreeSet ) and encapsulate the player information (including the score) into a specific class: 最简单的方法是使用Set (即TreeSet )并将玩家信息(包括得分)封装到特定的类中:

public class CompetitivePlayer implements Comparable<CompetitivePlayer>{

    private String name;
    private int score;    

    public CompetitivePlayer(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

    public void incrementScore() {
        score++;
    }

    @Override
    public int compareTo(CompetitivePlayer o) {
        return score - o.score;
    }
}

TreeSet assumes that entires stored in it implement the Comparable interface for determining the natural ordering of its elements. TreeSet假定存储在其中的整体实现了Comparable接口,用于确定其元素的自然顺序。

Edit: 编辑:

If you need to frequently modify the scores of players, then a Map<String, Integer> -based solution is a better fit, because there's no get in Java's Set . 如果你需要频繁修改玩家的分数,那么Map<String, Integer>为基础的解决方案是一个更好的贴合,因为没有get Java的Set This thread discusses the Map -based approach in great detail. 该主题详细讨论了基于Map的方法。

One simplictic solution (as suggested in the mentioned thread) is a one-liner, using the Guava library: 一种简单的解决方案(如上述线程中所述)是使用Guava库的单行代码:

Map<String, Integer> sortedScores = ImmutableSortedMap.copyOf(scores,
    Ordering.natural().onResultOf(Functions.forMap(scores)));

Use Collections .sort() and provide a custom Comparator to sort a map based on its values : 使用Collections .sort()并提供一个自定义的Comparator根据其值对地图进行排序:

Collections.sort( map, new Comparator<Map.Entry<K, V>>()
{
    @Override
    public int compare( Map.Entry<K, V> entry1, Map.Entry<K, V> entry2)
    {
        return (entry1.getValue()).compareTo( entry2.getValue() );
    }
} );

Can you rewrite your name and score as a class player, then you can use TreeSet to keep the order, and override equals() and compareTo(), it seems like you want to use name as identifier, and keep players ordered by score, then you can do 您可以改写您的姓名和得分作为班级选手吗,然后可以使用TreeSet保持顺序,并覆盖equals()和compareTo(),似乎您想使用名称作为标识符,并按得分保持选手排名,那你就可以

@Override
public boolean equals(Object obj) {
    if(obj instanceof Player)
        return this.name.equals(((Player)obj).name);
    return false;
}
@Override
public int compareTo(Player p) {
    return p.score - this.score;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM