I have the following scenario:
class Task {
int id;
Group group;
User user;
boolean successful;
}
User is part of Group, and Group-User relationship is many-to-many (user may belong to multiple groups and a group may contain multiple users). Task is specific to a User in a Group.
There is a List<Task> for which I need to summarize the number of successful tasks per User in a Group and send update to the user. So, if a user belongs to several groups I need to update him once for each group he belongs to (with the number of successful tasks the user had for that group).
What would be the best way to achieve that? Our current algorithm is:
First, sort the list by Group ID and then by User ID.
Then:
int successfulTasks = 0;
Group curGroup = null;
User curUser = null;
for(Task task : tasksByGroupAndUser) {
if((task.getGroup() != curGroup) || (task.getUser() != curUser) {
// Going to next user or group, update the previous user
updateUser(user,group, successfulTasks);
successfulTasks = 0;
}
if(task.isSuccessful()) {
successfulTasks++;
}
}
// Handle last user
if(curUser != null) {
updateUser(user,group, successfulTasks);
}
Is there a better (cleaner) way to do this? The above seems somewhat error-prone, especially that last user check.
You can create a
Pairclass which will haveUserandGroupas final fields. Make surePairoverrideshashCode()andequals().Create a
HashMap<Pair,Integer>, and maintain it [as a histogram] while iterating the list. [Need only one pass on the list for that].Later, iterate the histogram, and send an update for every
Pair[which is actually a tuple:(User,Group)] with the key – containing succesful runs.Should look something like: [Pseudo-code, there might be some syntatic errors…]:
This solution is asymptotically faster then the suggested solution since it is not requires sorting – so the total runtime is
O(n). [while the algorithm suggested in the question isO(nlogn)].Also: I find this solution easier to understand, but that might be a matter of opinion…