Home  >  Q&A  >  body text

java-ee - java8的Collectors.reducing()

Map<Integer, OperationCountVO> collect = operationInfos.stream().collect(Collectors.groupingBy(OperationCountVO::getCityId,
            Collectors.reducing(new OperationCountVO(), (OperationCountVO v1, OperationCountVO v2) -> {
                v1.setSurgeryCount(v1.getSurgeryCount() + v2.getSurgeryCount());
                v1.setCityId(v2.getCityId());
                return v1;
            })));

Probably I want to group the operationInfos collection according to the cityId in it, and then if the cityId is the same, add the SurgeryCount of the object and return it, but now the first v1 is null,
execute v1.setSurgeryCount(v1. getSurgeryCount() v2.getSurgeryCount()); reported a null pointer, is there something wrong with where I wrote it?

三叔三叔2686 days ago1300

reply all(1)I'll reply

  • 伊谢尔伦

    伊谢尔伦2017-07-03 11:45:35

    If v1 is null, it means that the operationInfos collection contains null, because it is grouped according to the cityId of OperationCountVO, then OperationCountVO must not be null, it is recommended Add filter directly in front to filter it out

    Map<Integer, OperationCountVO> collect = operationInfos.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(OperationCountVO::getCityId,
                Collectors.reducing(new OperationCountVO(), (OperationCountVO v1, OperationCountVO v2) -> {
                    v1.setSurgeryCount(v1.getSurgeryCount() + v2.getSurgeryCount());
                    v1.setCityId(v2.getCityId());
                    return v1;
                })));

    I just commented and found... The possible reason for the error is that the first parameter in Collectors.reducing is new OperationCountVO(), if the OperationCountVO object from new has a surgeryCount of If the Integer type is not a basic type, so it is not initialized, the surgeryCount will be null, and an error may be reported when doing the v1.getSurgeryCount() + v2.getSurgeryCount() operation

    (ps: For the second parameter BinaryOperator in reducing, it is best to encapsulate it into the OperationCountVO object. The code looks more declarative... It’s too ugly to write code like this... haha. ..Or write it out, it’s better to write it as a static final variable, so it can be called everywhere)

    For example, add a SurgeryCount attribute merged BinaryOperator directly to this class, and the name is surgeryCountMerge

    public static final BinaryOperator<OperationCountVO> surgeryCountMerge = (v1, v2) -> {
        v1.setSurgeryCount(v1.getSurgeryCount() + v2.getSurgeryCount());
        return v1;
    }

    The following code can be changed to

    Map<Integer, OperationCountVO> collect = operationInfos.stream()
            .filter(Objects::nonNull)
            .collect(Collectors.groupingBy(OperationCountVO::getCityId,
                                    Collectors.reducing(new OperationCountVO(), surgeryCountMerge));

    After writing this, I actually found that the question may be a bit troublesome. In the end, it is just to return a Map, so it is recommended not to use groupingBy. After all, the grouping return result is a one-to-many structure, not a pair. 1 structure, then use toMap directly, just click

    Map<Integer, OperationCountVO> collect = operationInfos.stream()
            .filter(Objects::nonNull)
            .collect(Collectors.toMap(OperationCountVO::getCityId, Function.identity(), surgeryCountMerge));

    This is much faster and no errors will be reported, haha

    reply
    0
  • Cancelreply