'Count the total boolean value of true using Java 8

Im using java 8. I have a class Operator which has 3 fields.

class Operator{
    private String type;
    private boolean updateRequested;
    private boolean deleteRequested;
}

I have list of Operator. I just want to count the updatedRequested and deleteRequested based on type whose value is true and add into the Map which is Map<String,Result>

class Result{
    private int deleteReqCount;
    private int updateReqCount;
}

Expected result

{
    "Cricket":{ deleteReqCount:10, updateReqCount:0},  // count only the value == `true`
    "Football":{ deleteReqCount:2, updateReqCount:10}, // count only the value == `true`
}

This question is bit simple and I did using for loops and if condition. But I'm impressed with Stream apis and Collectors framework. I'm a beginner, so tried list.stream().collect(Collectors.groupingBy(g -> g.getType())); but couldn't go further.

Thanks in advance



Solution 1:[1]

Here is an implementation using Collectors.toMap

class Operator {
    public String type;
    public boolean updateRequested;
    public boolean deleteRequested;
    Operator(String type, boolean updateRequested, boolean deleteRequested) {
        this.type = type;
        this.updateRequested = updateRequested;
        this.deleteRequested = deleteRequested;
    }
}

class Result {
    public int deleteReqCount;
    public int updateReqCount;
    Result(int deleteReqCount, int updateReqCount) {
        this.deleteReqCount = deleteReqCount;
        this.updateReqCount = updateReqCount;
    }

    @Override
    public String toString() {
        return "Result{" +
                "deleteReqCount=" + deleteReqCount +
                ", updateReqCount=" + updateReqCount +
                '}';
    }
}

Map<String, Result> solve(List<Operator> operatorList) {
    return operatorList.stream()
            .collect(Collectors.toMap(
                    v -> v.type,
                    v -> new Result(v.deleteRequested ? 1 : 0, v.updateRequested ? 1 : 0),
                    (result, result2) -> {
                        int deleteReqCount = result.deleteReqCount + result2.deleteReqCount;
                        int updateReqCount = result.updateReqCount + result2.updateReqCount;
                        return new Result(deleteReqCount, updateReqCount);
                    }
            ));
}

List<Operator> operatorList = Arrays.asList(
        new Operator("cricket", true, true),
        new Operator("cricket", true, false),
        new Operator("cricket", true, true),
        new Operator("soccer", false, true),
        new Operator("soccer", true, true)
);
System.out.println(solve(operatorList));

Output:

{soccer=Result{deleteReqCount=2, updateReqCount=1}, cricket=Result{deleteReqCount=2, updateReqCount=3}}

Solution 2:[2]

An update to Sai Kiran's excellent answer:

Map<String, Result> solve(List<Operator> operatorList) {
    return operatorList.stream()
        .collect(Collectors.toMap(
                v -> v.type,
                v -> new Result(v.deleteRequested ? 1 : 0, v.updateRequested ? 1 : 0),
                (result, result2) -> {
                    result.updateReqCount += result2.updateReqCount;
                    result.deleteReqCount += result2.deleteReqCount;
                    return result;
                }
        ));
}

Solution 3:[3]

As per comment by @Andreas,

    operators.stream().collect(Collectors.toMap(
            Operator::getType,
            v -> new Result(v.isDeleteRequested() ? 1 : 0, v.isUpdateRequested() ? 1 : 0),
            Result::merge
    ));

Merge method,

  public Result merge(Result result) {
      this.updateReqCount+=result.updateReqCount;
      this.deleteReqCount+=result.deleteReqCount;
      
      return this;
  }

Solution 4:[4]

For the time when you update to Java 12 or higher, the task can be achieved using Collectors.teeing :

List<Operator> ops = //your operators list

Map<String, Result> myMap =          
    ops.stream()
       .collect(
            Collectors.groupingBy(Operator::getType,
                 Collectors.teeing(
                           Collectors.filtering(Operator::isUpdateRequested,Collectors.counting()),
                           Collectors.filtering(Operator::isDeleteRequested,Collectors.counting()),
                           (updateCount, deleteCount) -> {
                                return new Result(updateCount.intValue(),deleteCount.intValue());
                           }
               )));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sai Kiran
Solution 2 K.Nicholas
Solution 3 Vikas Yadav
Solution 4 Eritrean