I have List of TrainingRequest where each and every element has List of Feedback.
@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.
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
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.
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:
{ "Q1": { "unsatisfied": 2, "Satisfied": 1, "satisfied": 1 }, "Q2": { "Yes": 4 } }
But I need it to give percentage as I expected
{ "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,
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()))))));