I have List of TrainingRequest where each and every element has List of Feedback.
JavaScript
x
@Data
class TrainingRequest{
@Transient
List<Feedack> feedback;
}
@Data
class Feedback{
String Q1;
String Q2;
}
I need to get all given result of Q1,Q2 and calculate percentage of each value.
JavaScript
List<TrainingRequest> trainingList = Optional.ofNullable(trainingRequestList).orElseGet(Collections::emptyList)
.stream().map(m -> {
List<Feedback> feedback = findByTrainingRequestId(m.getId());
m.setFeedback(feedback); // assigning Feedack to TrainingRequest
return m;
}).collect(Collectors.toList());
To flat all the feedback
JavaScript
List<Feedback> flatMap = trainingList.stream().flatMap(f -> f.getFeedback().stream()).collect(Collectors.toList());
To calculate each value of Q1 and Q2, I’m grouping it and getting the count. I need to get the percentage of each Q1, Q2 value insted of count.
JavaScript
Map<String, Map<String, Long>> map = new TreeMap<>();
map.put("Q1", flatMap.stream().collect(Collectors.groupingBy(Feedback::getQ1, Collectors.counting())));
map.put("Q2", flatMap.stream().collect(Collectors.groupingBy(Feedback::getQ2, Collectors.counting())));
When I use Collectors.counting()
, it’s giving the following output:
JavaScript
{
"Q1": {
"unsatisfied": 2,
"Satisfied": 1,
"satisfied": 1
},
"Q2": {
"Yes": 4
}
}
But I need it to give percentage as I expected
JavaScript
{
"Q1": {
"unsatisfied": 50 %,
"Satisfied": 25 %,
"satisfied": 25 %
},
"Q2": {
"Yes": 100 %
}
}
How to do it in a efficient way? Do I need to optimize the above code?
Advertisement
Answer
This might not be an optimized answer but you can get the result. Create a map to keep total values for each Q, and then use it to calculate percentage,
JavaScript
Map<String, Long> totalCountMap = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().values().stream().reduce(Long::sum).orElse(0l)));
Map<String, Map<String, Long>> result = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e1 -> (e1.getValue() * 100 / totalCountMap.get(e.getKey()))))));