The POJO viz. Entry.java represents an entry in the leaderboard. Position is the position in the leaderboard, 1 being the user with the highest score
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 + "]";
}
}
These entries are stored in a Map in a class as shown below :
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;
}
}
The method getLeaderBoard() is supposed to return
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
.
I couldn't figure out the predicate to use to return exactly 5 entries, including the one being searched for. Another aspect is performance since the leaderBoard can have hundreds of thousands of entries.
**********Edit-1**********
The following snippet provided by @nullpointer does the trick but I have some points on my mind
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);
Note : The leaderBoardUserEntryMap can have millions of entries
The indexOfnewEntry and +- 2 can cause IndexOutOfBoundsException, guarding against it seems a bit tedious, any optimal ways here?
Will using parallelStream() cause problems ?
List entries = leaderBoardUserEntryMap.entrySet().parallelStream().sorted(Map.Entry.comparingByValue(Comparator.comparing(Entry::getScore, Integer::compare).reversed())).parallel(). map(Map.Entry::getValue).collect(Collectors.toList());