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:
int sum = offences.stream()
.mapToInt(OffenceEntity::getPenaltyPoints)
.sum();
but I do not know how to "jump" to the set in OffenceEntity
CodePudding user response:
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.