按排序顺序存储条目(自定义pojo)并检索条目

时间:2017-09-13 12:14:15

标签: java collections java-8 java-stream

我正在尝试模拟一个游戏板,其中多个玩家可以提交他们的游戏分数。

POJO即。 Entry.java表示排行榜中的条目。 请注意覆盖的equals()方法

  

排名是排行榜中的位置,1是用户的排名   得分最高

public class Entry {

private String uid;
private int score;
private int position;

public Entry(String uid, int score) {

    this.uid = uid;
    this.score = score;

}

public Entry() {

}

public String getUid() {
    return uid;
}

public void setUid(String uid) {
    this.uid = uid;
}

public int getScore() {
    return score;
}

public void setScore(int score) {
    this.score = score;
}

public int getPosition() {
    return position;
}

public void setPosition(int position) {
    this.position = position;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + score;
    result = prime * result + ((uid == null) ? 0 : uid.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Entry other = (Entry) obj;
    if (score != other.score)
        return false;
    if (uid == null) {
        if (other.uid != null)
            return false;
    } else if (!uid.equals(other.uid))
        return false;
    return true;
}

@Override
public String toString() {
    return "Entry [uid=" + uid + ", score=" + score + ", position=" + position + "]";
}

}

GameBoard类有几种方法:

  • submitScore(String uid,int score) 每个玩家都会调用此方法将他的分数提交给游戏板。每个玩家/用户只有一个条目,因此,如果玩家多次调用此方法,则会存储他的最新分数
  • getLeaderBoard(String uid)
  

如果用户在排行榜中,则返回最多两个条目   比用户更高的分数(直接位于用户之上的用户)   用户在排行榜中),用户自己的条目和最多两个条目   紧接在排行榜中的用户之后

例如:

The leader board is :
Entry [uid=user1, score=14, position=1]
Entry [uid=user2, score=8, position=2]
Entry [uid=user3, score=7, position=3]
Entry [uid=user4, score=7, position=3]
Entry [uid=user5, score=4, position=4]
Entry [uid=user6, score=3, position=5]
Entry [uid=user7, score=3, position=5]
Entry [uid=user8, score=1, position=6]

For user5, entries returned should be :
Entry [uid=user3, score=7, position=3]
Entry [uid=user4, score=7, position=3]
Entry [uid=user5, score=4, position=4]
Entry [uid=user6, score=3, position=5]
Entry [uid=user7, score=3, position=5]

For user4, entries returned should be :
Entry [uid=user1, score=14, position=1]
Entry [uid=user2, score=8, position=2]
Entry [uid=user4, score=7, position=3]
Entry [uid=user5, score=4, position=4]
Entry [uid=user6, score=3, position=5]

For user6, entries returned should be :
Entry [uid=user4, score=7, position=3]
Entry [uid=user5, score=4, position=4]
Entry [uid=user6, score=3, position=5]
Entry [uid=user8, score=1, position=6]

For user7, entries returned should be :

Entry [uid=user4, score=7, position=3]
Entry [uid=user5, score=4, position=4]
Entry [uid=user7, score=3, position=5]
Entry [uid=user8, score=1, position=6]

我决定使用HashMap作为排行榜。

public class GameDefault {

    private Map<String, Entry> leaderBoardUserEntryMap;

    {
        leaderBoardUserEntryMap = new HashMap<>();
    }


    public void submitScore(String uid, int score) {

        Entry newEntry = new Entry(uid, score);
        leaderBoardUserEntryMap.put(uid, newEntry);
    }

    public List<Entry> getLeaderBoard(String uid) {

        if (!leaderBoardUserEntryMap.containsKey(uid))
            return Collections.emptyList();

        List<Entry> entriesOptionOne = leaderBoardUserEntryMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed()))
                .map(Map.Entry::getValue).collect(Collectors.toList());

        System.out.println("---------Current leader board---------");
        entriesOptionOne.forEach(System.out::println);

        if (entriesOptionOne != null && !entriesOptionOne.isEmpty()) {
            int indexOfUserEntry = entriesOptionOne.indexOf(leaderBoardUserEntryMap.get(uid));
            return CollectionUtil.getSubList(entriesOptionOne, indexOfUserEntry - 2, indexOfUserEntry + 3);
        }

        return Collections.emptyList();
    }

}

现在,存在以下问题和疑虑:

  • 程序没有返回正确的条目,因为我使用的是索引和子列表,所需要的就像是&#39; higherKey(key)&#39; &安培; &#39; lowerKey(键)&#39;在TreeMap中
  • 何时(理想情况下,在submitScore()期间)以及&#39;位置&#39;虽然它用于键,我想知道Map.compute()是否可以以任何方式提供帮助!
  • 由于排行榜甚至可以有一百万个条目,因此在每次调用getLeaderBoard()时排序然后检索似乎都是不可行的。我尝试使用Entry-Uid的SortedMap(TreeMap),但equals() doc中的SortedMap合同是一个挑战
  

请注意由排序地图维护的排序(无论是否为   提供显式比较器)如果必须与equals一致   有序映射是为了正确实现Map接口。 (见   可比较的接口或Comparator接口,用于精确定义   与equals一致的。)这是因为Map接口是   根据等于操作定义,但有序映射执行   所有关键比较使用compareTo(或compare)方法,所以两个   从这个方面来看,被认为是相同的密钥是   有序的地图,相等。甚至可以很好地定义树图的行为   如果它的排序与equals不一致;它只是没有服从   Map接口的一般合同。

0 个答案:

没有答案