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()应该返回
最多两个分数大于用户的分数(用户分数) 位于排行榜中的用户之上,即用户自己的用户 条目中的条目和最多两个条目紧跟在用户之后 排行榜
我无法弄清楚用于返回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());
答案 0 :(得分:1)
Stream#limit
将帮助您限制在您创建的反向列表中找到最高N
(5)个用户,并且您还可以映射列表&gt;使用这些值并最终从中收集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用例
说有100个用户,正在搜索的用户是93。 列表应返回91,92,93,94,95。此解决方案将返回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 :
indexOfnewEntry和+ - 2会导致IndexOutOfBoundsException, 防范它看起来有点乏味,这里有什么最佳方式吗?
由于条目的index
可能会因分数而异,subList
访问权限还会依赖于之前/之后所需的输出数量。保护应该是比任何其他保护更好的选择。另外可以考虑的是customSubList实现,它可以在内部检查您的集合类型。 How to use subList()以最高投票答案解释了这一点。我特别喜欢这个:
dataList.subList(Math.max(0, first), Math.min(dataList.size(), last) );
使用
parallelStream()
会导致问题吗?
除非执行任何synchronized
块可能会改变并对流进行并发更新,否则不会造成任何问题。
但您应该知道何时使用并行流 - Should I always use a parallel stream when possible?