'java 8 stream for double loop and change the value in first loop

i have nested loop to loop and change the first list based on condition below. this works fine.

its like if cardNumber in firstList same or found in secondList, copy properties from secondList to firstList.

for (int i = 0; i < listFirst.size(); i++) {
    for (int j = 0; j < listSecond.size(); j++) {
        if (StringUtils.equals(listFirst.get(i).getCardNumber(), listSecond.get(j).getCardNumber())) {
            try {
                 listFirst.get(i).setSubmitDate(listSecond.get(j).getIssueDate());
                 listFirst.get(i).setPersonalNumber(listSecond.get(j).getPersonalNumber());
                 listFirst.get(i).setMembershipPeriod(listSecond.get(j).getPeriod());
                 listFirst.get(i).setPhoneNumber(listSecond.get(j).getMobileNo());
                 listFirst.get(i).setIdCardNumber(listSecond.get(j).getIdNumber());
                 listFirst.get(i).setMoney(listSecond.get(j).getLoanAmount().toString());
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
        }
    }
}

i just want to know is this possible in java 8 stream? or lambda expression? i've tried using stream, for each, but sometimes i got confused.



Solution 1:[1]

Assuming that Foo is your class, we can form a cartesian product of items of the 2 lists, and then filter by some property (cardNumber equality). Then, matching pairs can be used in a forEach stream-terminating method.

listFirst.stream()
   .flatMap(t -> listSecond.stream().map(s -> new Foo[] {t, s}))
   .filter(pair -> StringUtils.equals(pair[0].getCardNumber(), pair[1].getCardNumber()))
   .forEach(pair -> {
       final Foo t = pair[0], s = pair[1]; // unpack pair
       // set individual properties here (or call a setup method) ...
       t.setSubmitDate(s.getIssueDate())
       // .... more sets ...
   }) 

Solution 2:[2]

With a little reorganization, yes:

If you were to add a method to the class in the first list to do the checks and assignments:

public void init(YourClass other) {
    if (StringUtils.equals(getCardNumber(), other.getCardNumber())) {
        try {
             setSubmitDate(other.getIssueDate());
             setPersonalNumber(other.getPersonalNumber());
             setMembershipPeriod(other.getPeriod());
             setPhoneNumber(other.getMobileNo());
             setIdCardNumber(other.getIdNumber());
             setMoney(other.getLoanAmount().toString());
         } catch (Exception e) {
             log.error(e.getMessage());
         }
    }
}

Then your loop can become:

listFirst.stream()
         .forEach(a -> listSecond.stream()
                                 .forEach(b -> a.init(b)));

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
Solution 2 Ryan