Skip to content

Calculate the percentage of value using Collection framework

I have List of TrainingRequest where each and every element has List of Feedback.

class TrainingRequest{
    List<Feedack> feedback;

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;

To flat all the feedback

List<Feedback> flatMap = -> 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",, Collectors.counting())));
map.put("Q2",, 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?


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()))))));