POJO即. Entry.
java
表示排行榜中的条目.排名是排行榜中的位置,1是得分最高的用户
public class Entry {
private String uid;
private int score;
private int 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;
if (!(obj instanceof Entry))
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 + "]";
}
}
这些条目存储在类中的Map中,如下所示:
public class GameDefault {
Map<String, Entry> leaderBoardUserEntryMap;
public void submitScore(String uid, int score) {
Entry newEntry = new Entry(uid, score);
leaderBoardUserEntryMap.put(uid, newEntry);
}
public List<Entry> getLeaderBoard(String uid) {
/* Option-3 : A Map of uid-Entry */
leaderBoardUserEntryMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed()))
.filter(/*What to put here*/);
return null;
}
}
方法getLeaderBoard()应该返回
max two entries that have larger score than the user (the users that
are immediately above the user in the leaderboard), the user’s own
entry and max two entries that are immediately after the user in the
leaderboard
.
我无法弄清楚用于返回5个条目的谓词,包括正在搜索的条目.另一个方面是性能,因为leaderBoard可以拥有数十万个条目.
**********编辑-1 **********
@nullpointer提供的以下片段可以解决这个问题,但我有一些观点
List<GameEntry> selectedEntries = leaderBoardUserEntryMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.comparing(GameEntry::getScore, Integer::compare)
.reversed())).map(Map.Entry::getValue).collect(Collectors.toList());
int indexOfnewEntry = selectedEntries.indexOf(leaderBoardUserEntryMap.get(uid));
return selectedEntries.subList(indexOfnewEntry-2,indexOfnewEntry+2);
注意:leaderBoardUserEntryMap可以有数百万条目
> indexOfnewEntry和 – 2可以导致IndexOutOfBoundsException,防止它看起来有点乏味,这里有什么最佳方式吗?
>使用parallelStream()会导致问题吗?
List entries = leaderBoardUserEntryMap.entrySet().parallelStream().sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry :: getScore,Integer :: compare).reversed())).parallel().
地图(Map.Entry的::的getValue).collect(Collectors.toList());
最佳答案
Stream#limit
将帮助您限制在您创建的反向列表中查找前N(5)个用户,并且您还可以映射列表>使用这些值并收集List< Entry>从它最终作为:
return leaderBoardUserEntryMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed()))
.limit(5).map(Map.Entry::getValue).collect(Collectors.toList());
编辑:感谢@Yogesh的用例
say there are 100 users, and the user that is being searched is at 93.
List should return 91, 92, 93, 94, 95. This solution will return 1, 2,
3, 4, 5
由于用例是在当前条目周围有一个subList
,因此可以修改为:
List<GameEntry> selectedEntries = leaderBoardUserEntryMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.comparing(GameEntry::getScore, Integer::compare)
.reversed())).map(Map.Entry::getValue).collect(Collectors.toList());
int indexOfnewEntry = selectedEntries.indexOf(leaderBoardUserEntryMap.get(uid));
return selectedEntries.subList(indexOfnewEntry-2,indexOfnewEntry+2);
编辑2:
The indexOfnewEntry and +- 2 can cause IndexOutOfBoundsException,
guarding against it seems a bit tedious, any optimal ways here?
由于条目的索引可能在分数上变化,并且子列表访问还进一步依赖于在其之前/之后所需的输出的数量.保护应该是比任何其他保护更好的选择.另外可以考虑的是customSubList实现,它可以在内部检查您的集合类型. How to use subList()以最高投票答案解释了这一点.我特别喜欢这个:
dataList.subList(Math.max(0, first), Math.min(dataList.size(), last) );
Will using
parallelStream()
cause problems?
除非执行的任何同步块可能会更改并对流进行并发更新,否则不会导致任何问题.
但你应该知道何时使用并行流 – Should I always use a parallel stream when possible?