I want to store key-value pairs <String, List> in a map and sort the entries based on the value (list of Data) of Key as per following logic:
I am looking get 1 result per group (A,B,C,D)
import java.util.ArrayList;
public class MyClass {
public static void main(String args[]) {
// output should be just Data(17.0, "five", "D"), Data(4.0, "two", "A"), Data(3.0, "three", "B")
ArrayList<Data> dataList = new ArrayList<Data>();
dataList.add(new Data(1.0, "one", "A"));
dataList.add(new Data(4.0, "two", "A"));
dataList.add(new Data(3.0, "three", "B"));
dataList.add(new Data(2.0, "four", "C"));
dataList.add(new Data(7.0, "five", "D"));
dataList.add(new Data(17.0, "five", "D"));
// output should be just Data(5.0, "six", "A"), Data(3.14, "two", "B"), Data(3.14, "three", "C")
ArrayList<Data> dataList2 = new ArrayList<Data>();
dataList2.add(new Data(3.0, "one", "A"));
dataList2.add(new Data(5.0, "six", "A"));
dataList2.add(new Data(3.14, "two", "B"));
dataList2.add(new Data(3.14, "three", "C"));
System.out.println("data 1= " + dataList.size());
System.out.println("data 2 = " + dataList2.size());
}
static class Data {
double score;
String name;
String group;
public Data(double score, String name, String group) {
score = this.score;
name = this.name;
group = this.group;
}
public String getName() {
return name;
}
public String getGroup() {
return group;
}
public double getScore() {
return score;
}
}
}
I know the procedural way to do this but is there a smarter/functional way to do it in Java 8?
I am looking get 1 result per group (A,B,C,D)
and
I want to store key-value pairs <String, List>
contradict each other somehow. But I assume that you want to have the entry with the highest score from each group and limit the result to some given size n
. If this is true try something like below to get a map with top n elements having group
as key and the Data
object itself as value
long n = 3;
Map<String,Data> result =
dataList.stream()
.collect(Collectors.groupingBy(Data::getGroup,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Data::getScore)),
Optional::get)))
.entrySet()
.stream()
.sorted(Comparator.comparing(e -> e.getValue().getScore(),Comparator.reverseOrder()))
.limit(n)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(a,b) -> a, LinkedHashMap::new));
result.entrySet().forEach(System.out::println);
to get
D=MyClass.Data(score=17.0, name=five, group=D)
A=MyClass.Data(score=4.0, name=two, group=A)
B=MyClass.Data(score=3.0, name=three, group=B)
Or if you just need a sublist of the list which contains the max score elements in each group (since the group value is available in the object itself), then do something like:
List<Data> result =
dataList.stream()
.collect(Collectors.groupingBy(Data::getGroup,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Data::getScore)),
Optional::get)))
.values()
.stream()
.sorted(Comparator.comparingDouble(Data::getScore).reversed())
.limit(n)
.collect(Collectors.toList());
result.forEach(System.out::println);
result.forEach(System.out::println);
to get
MyClass.Data(score=17.0, name=five, group=D)
MyClass.Data(score=4.0, name=two, group=A)
MyClass.Data(score=3.0, name=three, group=B)