Jesse
Jesse

Reputation: 93

Java8: change the reference of the variable outside of forEach

I try to do two things at once:

1.Sum values from specific field of the objects in a list

AtomicReference<BigDecimal> doReqQtySum = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<BigDecimal> boQtySum = new AtomicReference<>(BigDecimal.ZERO);
models.forEach(detail -> {
    doReqQtySum.accumulateAndGet(detail.getDoReqQty(), (bg1, bg2) -> bg1.add(bg2));
    boQtySum.accumulateAndGet(detail.getBoQty(),  (bg1, bg2) -> bg1.add(bg2));
});

2.Filter a object from list

DoRequestDetailModel originProductRequestDetail = models.stream()
    .filter(m -> m.getIsOriginProduct())
    .reduce((a, b) -> {
         throw new IllegalStateException();
    })
    .get();

I would like this code, but it dosen't work:

AtomicReference<BigDecimal> doReqQtySum = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<BigDecimal> boQtySum = new AtomicReference<>(BigDecimal.ZERO);
DoRequestDetailModel originProductRequestDetail = new DoRequestDetailModel();
models.forEach(detail -> {
     doReqQtySum.accumulateAndGet(detail.getDoReqQty(), (bg1, bg2) -> bg1.add(bg2));
     boQtySum.accumulateAndGet(detail.getBoQty(),  (bg1, bg2) -> bg1.add(bg2));
     if(detail.getIsOriginProduct()) {
          originProductRequestDetail = detail;
     }
});

The next code could be done

AtomicReference<BigDecimal> doReqQtySum = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<BigDecimal> boQtySum = new AtomicReference<>(BigDecimal.ZERO);
List<DoRequestDetailModel> tempList = new ArrayList<>();
models.forEach(detail -> {
    doReqQtySum.accumulateAndGet(detail.getDoReqQty(), (bg1, bg2) -> bg1.add(bg2));
    boQtySum.accumulateAndGet(detail.getBoQty(),  (bg1, bg2) -> bg1.add(bg2));
    if(detail.getIsOriginProduct()) {
         tempList.add(detail);
    }
});

Is there a better solution ?

Upvotes: 2

Views: 983

Answers (1)

Andronicus
Andronicus

Reputation: 26076

You would have to use AtomicReference as well:

AtomicReference<BigDecimal> doReqQtySum = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<BigDecimal> boQtySum = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<DoRequestDetailModel> originProductRequestDetail = new AtomicReference<>(new DoRequestDetailModel());
models.forEach(detail -> {
     doReqQtySum.accumulateAndGet(detail.getDoReqQty(), (bg1, bg2) -> bg1.add(bg2));
     boQtySum.accumulateAndGet(detail.getBoQty(),  (bg1, bg2) -> bg1.add(bg2));
     if(detail.getIsOriginProduct()) {
          if(originProductRequestDetail.get()) throw new IllegalStateException();
          originProductRequestDetail.set(detail);
     }
});

It's because you're changing a reference of an outside variable in the scope of the function invoked inside forEach. Here is a related question.

Upvotes: 1

Related Questions