Reputation: 53
I have a List<Records> =
[
{"studentId": "001", "date": "20180705", "courseId": "CS220", "score": "80"},
{"studentId": "001", "date": "20180702", "courseId": "CS320", "score": "75"},
{"studentId": "001", "date": "20180704", "courseId": "CS330", "score": "90"},
{"studentId": "002", "date": "20180703", "courseId": "CS640", "score": "95"},
{"studentId": "002", "date": "20180628", "courseId": "CS530", "score": "80"},
{"studentId": "002", "date": "20180701", "courseId": "CS545", "score": "90"},
{"studentId": "100", "date": "20180708", "courseId": "CS542", "score": "80"},
{"studentId": "100", "date": "20180629", "courseId": "CS240", "score": "97"},
...
]
How can I group the objects by same studentId
and just keep the one which has highest score in list? like following:
List<Records> =
[
{"studentId": "001", "date": "20180704", "courseId": "CS330", "score": "90"},
{"studentId": "002", "date": "20180703", "courseId": "CS640", "score": "95"},
{"studentId": "100", "date": "20180629", "courseId": "CS240", "score": "97"},
...
]
Upvotes: 0
Views: 216
Reputation: 14572
Using a Stream
to collect the value. You can find an example on Baeldung -- Guide to Java 8 groupingBy Collector
2.8. Getting the Maximum or Minimum from Grouped Results
This could be used like :
records.stream()
.collect(
Collectors.groupingBy(
Record::getStudentId,
Collectors.maxBy(Compartor.comparingInt(Record::getPoint))
)
);
The map returned will have each studentId
as a key and the instance with the maximum value. Example using a POJO :
class POJO {
String name;
int value;
//getters
//toString //POJO [%name% %value%]
}
And the quick test :
Map<String, Optional<POJO>> map = Stream.of(
new POJO("A", 1), new POJO("A", 2), new POJO("A", 10),
new POJO("B", 8), new POJO("B", 4),
new POJO("C", 4),
new POJO("D", 4), new POJO("D", 1), new POJO("D", 2)
).collect(
Collectors.groupingBy(
POJO::getName,
Collectors.maxBy(
Comparator.comparingInt(POJO::getValue)
)
)
);
System.out.println(map);
{A=Optional[POJO [A 10]],
B=Optional[POJO [B 8]],
C=Optional[POJO [C 4]],
D=Optional[POJO [D 4]]}
Upvotes: 1
Reputation: 4114
This can be done with java8's stream.
records.stream()
.collect(Collectors.toMap(Records::getStudentId ,Records::getScore,(s1,s2)->Math.max(s1,s2)))
The 3rd param (merge function) of the toMap method always selects the greater score value.
Upvotes: 1