java - Retrieve fixed number of entries around an entry in a map sorted by values -


the pojo viz. entry.java represents entry in leaderboard. position position in leaderboard, 1 being user 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 stored in map in class 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 : map of uid-entry */     leaderboarduserentrymap.entryset().stream().sorted(map.entry.comparingbyvalue(comparator.comparing(entry::getscore, integer::compare).reversed()))                 .filter(/*what put here*/);          return null;     } } 

the method getleaderboard() supposed return

max 2 entries have larger score user (the users above user in leaderboard), user’s own entry , max 2 entries after user in leaderboard

.

i couldn't figure out predicate use return 5 entries, including 1 being searched for. aspect performance since leaderboard can have hundreds of thousands of entries.

**********edit-1**********

the following snippet provided @nullpointer trick have points on 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 : leaderboarduserentrymap can have millions of entries

  • the indexofnewentry , +- 2 can cause indexoutofboundsexception, guarding against seems bit tedious, 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());

stream#limit shall restrict finding top n(5) users on reversed list you've created , further can map list> using values , collect list<entry> as:

return leaderboarduserentrymap.entryset().stream()             .sorted(map.entry.comparingbyvalue(comparator.comparing(entry::getscore, integer::compare).reversed()))             .limit(5).map(map.entry::getvalue).collect(collectors.tolist()); 

edit: @yogesh use case

say there 100 users, , user being searched @ 93. list should return 91, 92, 93, 94, 95. solution return 1, 2, 3, 4, 5

since use case have sublist around current entry, modified as:

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); 

edit 2:

the indexofnewentry , +- 2 can cause indexoutofboundsexception, guarding against seems bit tedious, optimal ways here?

since index of entry might vary on score, , sublist access further relies on number of output desired before/after it. guarding shall better option other. considered customsublist implementation internally check collection type. how use sublist() explains top voted answers. liked 1 though :

datalist.sublist(math.max(0, first), math.min(datalist.size(), last) ); 

will using parallelstream() cause problems?

unless there synchronized blocks executed might alter , make concurrent updates stream wouldn't cause problems.

but should know when use parallel stream - should use parallel stream when possible?


Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -