Home > Enterprise >  How to Add up the values in a Nested Collection using Streams
How to Add up the values in a Nested Collection using Streams

Time:08-09

I have the following TicketDTO Object:

public class TicketDTO {
    private LocalDate date;
    private Set<OffenceDTO> offences;
}

And every OffenceDTO has an int field - penalty points.

public class OffenceDTO {
    private int penaltyPoints;
}

I would like to add up the penalty points to a single int value by streaming the Set of Offenses of each Ticket. But only if the ticket's date is between the last two years.

I have collected tickets from the last two years, but now I have a problem in how to go through the offenses and count their points.

This is what I've written so far:

tickets().stream()
    .filter(ticketEntity -> isDateBetween(LocalDate.now(), ticketEntity.getDate()))
    .collect(Collectors.toList());

CodePudding user response:

Assuming that tickets() is a method that returns a List of TicketDTO, you could stream the List and filter its elements with your custom method isDateBetween (as you were doing).

Then flat the mapping of each ticket to their corresponding offences. This will provide you a stream of OffenceDTO whose TicketDTO is between the last two years (according to your isDateBetween method).

Ultimately, you can collect the points of each OffenceDTO by summing them with the summingInt method of the Collectors class.

int res = tickets().stream()
        .filter(ticketEntity -> isDateBetween(LocalDate.now(), ticketEntity.getDate()))
        .flatMap(ticketDTO -> ticketDTO.getOffences().stream())
        .collect(Collectors.summingInt(OffenceDTO::getPoints));

CodePudding user response:

I would like to collect the penalty points in a single int value by streaming the set of tickets

It can be done in the following steps:

  • Turn the stream of filtered tickets into a stream of OffenceDTO using flatMap();
  • Extract penalty points from OffenceDTO with mapToInt(), that will transform a stream of objects into a IntStream;
  • Apply sum() to get the total.
int totalPenalty = tickets().stream()
    .filter(ticketEntity -> isDateBetween(LocalDate.now(), ticketEntity.getDate()))
    .flatMap(ticketDTO -> ticketDTO.getOffences().stream())
    .mapToInt(OffenceDTO::getPenaltyPoints)
    .sum();
  • Related