Home > Software engineering >  Get date from the List of newborn on which the most children were born
Get date from the List of newborn on which the most children were born

Time:04-01

I have a File.txt (represent NewBorn).

I've created a class NewBorn that has the following fields: id, name, age.

Then I'm reading the file and parsing it, so I can get a nice output.

From the list of newborn (based on file.txt) I need to get the date on which the most children were born, but I have a problem filtering through that.

That's what I've tried :

public static List<NewBorn> dateInWitchMostChildrenAreBorn(List<NewBorn> newBornList) {
    return newBornList.stream()
            .filter(newBorn -> newBorn.getBirthdate() // in here I tried to go use =  but is not good of course  )
            //then I want to collect that and  count the one that is the most in witch  children are born
            .collect((Collectors.toSet()));
}

CodePudding user response:

Here, First filtering the null birthdate, then grouping it by birthdate then collecting it to a Map with birthdate as key and occurrence as value, then returning the max occurrence birthdate

public static LocalDate dateInWitchMostChildrenAreBorn(List<NewBorn> newBornList) {
    return newBornList.stream()
        .filter(newBorn -> Objects.nonNull(newBorn.getBirthdate()))
        .collect(Collectors.groupingBy(NewBorn::getBirthdate, Collectors.counting()))
        .entrySet().stream()
        .max(Map.Entry.comparingByValue())
        .map(Map.Entry::getKey).orElse(null);
}

CodePudding user response:

There could be multiple dates for which the numbers of children have been born are equal. Therefore, there can be more than one date that corresponds to the maximum number of newborns. Maybe that's why the method listed in the question is meant to return a list.

In order to obtain the List<LocalDate> containing all dates when number of newborns is maximal, first, we need to create map Map<LocalDate, Long> (number of newborns by date) by using collector Collectors.groupingBy(). The function that extracts the birthdate is used as the first argument and Collectors.counting(), that generates the number of elements mapped to a key, as a downstream collector.

Then we can generate the resulting list in a single pass over the entries of this map with a custom collector that will collect the entries having the highest previously encountered count. If the next entry has a value greater the previous maximum, intermediate results will be cleaned up.

To implement a custom collector, we can utilize the static method of() defined in the Collector interface.

ArrayDeque is used as mutable container of the collector.

The finisher function creates a stream over the resulting queue, which extracts date objects from the entries and collect them into a list.

public static List<LocalDate> dateInWitchMostChildrenAreBorn(List<NewBorn> newBornList) {
    return newBornList.stream()
            .collect(Collectors.groupingBy(NewBorn::getBirthdate,
                                           Collectors.counting())) // Map<LocalDate, Long> - number of newborns by date
            .entrySet().stream()
            .collect(Collector.of(
                    ArrayDeque::new, // supplier
                    (Queue<Map.Entry<LocalDate, Long>> queue,
                     Map.Entry<LocalDate, Long> next) -> { // accumulator
                        if (!queue.isEmpty() && queue.element().getValue() < next.getValue()) queue.clear();
                        if (queue.isEmpty() || queue.element().getValue().equals(next.getValue())) queue.add(next);
                    },
                    (Queue<Map.Entry<LocalDate, Long>> left,
                     Queue<Map.Entry<LocalDate, Long>> right) -> { // combiner
                        if (left.isEmpty()) return right;
                        if (right.isEmpty()) return left;
                        if (left.element().getValue() < right.element().getValue()) return right;
                        if (left.element().getValue() > right.element().getValue()) return left;
                        else {left.addAll(right); return left;}
                    },
                    (Queue<Map.Entry<LocalDate, Long>> queue) -> // finisher
                            queue.stream().map(Map.Entry::getKey).toList()
            ));
}

main() - demo

public static void main(String[] args) {
    List<NewBorn> newBorns =
            List.of(new NewBorn(LocalDate.of(2021, 1, 5)),
                    new NewBorn(LocalDate.of(2021, 3, 8)),
                    new NewBorn(LocalDate.of(2021, 3, 8)),
                    new NewBorn(LocalDate.of(2021, 12, 10)),
                    new NewBorn(LocalDate.of(2021, 12, 10)),
                    new NewBorn(LocalDate.of(2021, 1, 5)),
                    new NewBorn(LocalDate.of(2021, 5, 25)),
                    new NewBorn(LocalDate.of(2021, 7, 12)));

    System.out.println(dateInWitchMostChildrenAreBorn(newBorns));
}

Output (expected : three dates on which the number of newborns is 2)

[2021-12-10, 2021-03-08, 2021-01-05]
  • Related