Hanuman M
Hanuman M

Reputation: 27

How do I replace below for loop code with Java 8 streams

In the below code i am trying to create a Set based on some conditions. I want to use java 8 streams and replace this code involving for loops. Any code example/sample will be much appreciated.

Set<OwnerEntity> entities = new LinkedHashSet<>();
for(Account acct : accounts){
    String acctNumber = acct.getAccountNumber();

    OwnerEntity oEntity = new OwnerEntity();
    oEntity.setAccount(acct);
    oEntity.setName(acct.getName());

    for (StatusModel sts : stsModels) {
        if ( sts.egtStatus() != null &&
                (acctNumber.equalsIgnoreCase(sts.getAccountNumber()))) {
            oEntity.addStatusModel(sts);
        }
    }

    entities.add(oEntity);
}

Upvotes: 0

Views: 100

Answers (2)

Youcef LAIDANI
Youcef LAIDANI

Reputation: 59950

I would like to make in two steps, like so :

First Step

If you note, you have that block of code which is repeated each time :

for (StatusModel sts : stsModels) {
    if ( sts.egtStatus() != null &&
            (acctNumber.equalsIgnoreCase(sts.getAccountNumber()))) {
        oEntity.addStatusModel(sts);
    }
}

In this case, you can group by the status, then you can call with your map to get the list of StatusModel by accountNumber, to do this you can use :

Map<String, List<StatusModel>> map = stsModels.stream()
        .filter(sts -> sts.getStatus() != null)
        .collect(Collectors.groupingBy(StatusModel::getAccountNumber));

Or more precise, you can group with status in lowerCase :

.collect(Collectors.groupingBy(s -> s.getStatus().toLowerCase()));

Second Step

Then, you can loop over the accounts and create a new OwnerEntity like so :

Set<OwnerEntity> entities = accounts.stream()
        .map(acct ->
                new OwnerEntity(acct,
                        acct.getName(),
                        map.getOrDefault(acct.getAccountNumber().toLowerCase(), Collections.emptyList())))
        .collect(Collectors.toSet());

Note: I used toLowerCase() in both side groupingBy and getOrDefault to avoid using looping over the list and check by using equalsIgnoreCase

Upvotes: 3

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147154

It should look something like:

Set<OwnerEntity> entities = accounts.stream()
    .map(acct -> {
        String acctNumber = acct.getAccountNumber();

        OwnerEntity oEntity = new OwnerEntity();
        oEntity.setAccount(acct);
        oEntity.setName(acct.getName());

        stsModels.stream()
           // You can do .filter as a two-parter with Objects::nonNull
           .filter(sts ->
              sts.egtStatus() != null &&
              acctNumber.equalsIgnoreCase(sts.getAccountNumber())
           )
           .forEach(oEntity::addStatusModel);
    })
    .collect(Collectors.toCollection(LinkedHashSet::new));

It's not much of an improvement, but that's streams for you.

Upvotes: 0

Related Questions