1

I have two classes Meeting and Guest.

The relation looks like this:

class Meeting {

private LocalDate date;
private List<Guest> guests;

}

I need to get one Meeting by date and where guests are from the USA using stream.

I have List and I have done the next one:

List<Meeting> meetings = new ArrayList<>();

public Meeting getByDay(LocalDate date) {
    List<Guest> guests = getGuestsByDate(date).stream()
            .filter(guest-> guest.getCountry().equals("USA"))
            .collect(Collectors.toList());
    return new Meeting(date, guests);
}

but now I need to refactor my code with custom Collector, which returns Meeting. I read it needs to implement the Collector interface or Collector.of() method but how it must look in my case? I would be grateful for any advice.

2
  • getGuestsByDate(date) would be more fun to know the implementation of. Commented Apr 16, 2021 at 10:35
  • 1
    .collect(Collectors.toList()).collect(Collectors.collectingAndThen(Collectors.toList(), l->new Meeting(date,l))) Commented Apr 16, 2021 at 16:40

3 Answers 3

2

I don't recommend this approach, but if you need, you can use:

    Meeting m = Stream.of(new Guest(), new Guest())
        .collect(Collector.of(
            () -> new Meeting(date),
            Meeting::addGuest,
            (m1, m2) -> {
              ArrayList<Guest> guestsAll = new ArrayList<>(m1.getGuests());
              guestsAll.addAll(m2.getGuests());
              return new Meeting(date, guestsAll);
            }
        ));

I added couple of constructors and method to Meeting class

    Meeting(LocalDate date) {
      this.date = date;
      this.guests = new ArrayList<>();
    }

    Meeting(LocalDate date, List<Guest> guests) {
      this.date = date;
      this.guests = guests;
    }

    public void addGuest(Guest g) {
      guests.add(g);
    }
Sign up to request clarification or add additional context in comments.

Comments

0

Although the question is about using Collector, you can use reduce operator as well. Try the below code:

public Meeting getByDay(LocalDate date) {   
    return getGuestsByDate(date).stream()
            .filter(guest -> guest.getCountry().equals("USA"))
            .reduce(new Meeting(date, new ArrayList<>()), (meeting, guest) -> {
                meeting.guests.add(guest);
                return meeting;
            }, (meeting1, meeting2) -> {
                meeting1.guests.addAll(meeting2.guests);
                return meeting1;
            });
}

You can shift those lambda expressions into the Meeting class or some other method and use method reference or one liner lambdas.

Comments

-1

I know this will not the full code but you will get an idea of how you can achieve the solution

 List<Meeting> meeting = meetings.stream()
        .filter(guest-> guest.getCountry().equals("USA"))
        .map(v->{ 
          return new Meeting(something, something);
         })
        .collect(Collectors.toList());

4 Comments

This code will return multiple meetings. Original code returns one meeting with multiple guests.
Ok bro, In that case, you need to return the map. For returning a single object type you can't use a collector. This is for the Map and list related return type. your existing code is fine.
Collector can return single object.
Collector<MyData, MyResult, MyResult> myCollector = Collector.of( () -> new MyResult(), (a, e) -> { if (e.key.equals("2")) { a.color = e.value; } }, (a1, a2) -> null, // Not used, therefore not working scaffold a -> a ); MyResult result = collection.stream().collect(myCollector);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.