Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to replace iter loops by stream

I am tryning to replace that code using stream.

public int countPenaltyPointsTest(Set<OffenceEntity> offences, LocalDate date) {
    int sum = 0;
    for (OffenceEntity offence : offences) {
        for (OffenceDetailsEntity offenceDetailsEntity : offence.getDetails()) {
            if (date.isAfter(offenceDetailsEntity.getStartDate())
                    && date.isBefore(offenceDetailsEntity.getEndDate())) {
                sum +=offenceDetailsEntity.getPenaltyPoints();
            }
        }
    }

I have OffenceEntity with OneToMany relationsh with OffenceDetailsEntity:

@Entity
public class OffenceEntity {
    ...
    private Set<OffenceDetailsEntity> details;
}


@Entity
public class OffenceDetailsEntity {
    ...
    private int penaltyPoints;
    private LocalDate startDate;
    private LocalDate endDate;
    @ManyToOne
    @JoinColumn(referencedColumnName = "id")
    private OffenceEntity offence;
}

and I would like to collect penalty points where date is between two dates.
I know how to do it for example when I have field like penalty points in OffenceEntity.
Example:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

int sum = offences.stream()
            .mapToInt(OffenceEntity::getPenaltyPoints)
            .sum();

but I do not know how to "jump" to the set in OffenceEntity

>Solution :

You need flatMap() operation (or its flavor flatMapToInt()) to flatten the data that corresponds to each OffenceEntity object.

public int countPenaltyPointsTest(Set<OffenceEntity> offences, LocalDate date) {
    
    return offences.stream()
        .flatMap(offence -> offence.getDetails().stream())
        .filter(ode -> date.isAfter(ode.getStartDate())
                        && date.isBefore(ode.getEndDate()))
        .mapToInt(OffenceDetailsEntity::getPenaltyPoints)
        .sum();
}

Since Java 16 we can also use mapMulty() operation for one-to-many transformations. This operation allows incorporating imperative programming features (i.e. loops and conditional statements) into the stream pipeline ().

Here’s how we can implement this method using mapMultyToInt():

public int countPenaltyPointsTest(Set<OffenceEntity> offences, LocalDate date) {
    
    return offences.stream()
        .mapMultiToInt((offence, consumer) -> 
            offence.getDetails().forEach(ode -> {
                if (date.isAfter(ode.getStartDate()) && date.isBefore(ode.getEndDate()))
                    consumer.accept(ode.getPenaltyPoints());
        }))
        .sum();
}

For more information on mapMulty() operation, have a look at this question.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading