Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

group list of objects by date and sort them time using rxjava

I have a list of restaurants' reservations. I want to group them by day of the year and sort them by time on that day. How can I do so using rxjava?

List reservations;

class Reservation {
   public String guestName;
   public long time; //time in milliseconds
}

OUTPUT

  • day 5th of March 2015
    • reservation for 20:00
    • reservation for 22:00
  • day 8th of of March 2015
    • reservation for 16:00
like image 650
Giorgio Avatar asked Dec 14 '22 15:12

Giorgio


2 Answers

To do this with RxJava, you could first sort your list by the time (toSortedList), then perform manual grouping in a flatMap, outputting an Observable<List<Reservation>> which gives you each day.

Observable.from(reservations)
    .toSortedList(new Func2<Reservation, Reservation, Integer>() {
        @Override
        public Integer call(Reservation reservation, Reservation reservation2) {
            return Long.compare(reservation.time, reservation2.time);
        }
    })
    .flatMap(new Func1<List<Reservation>, Observable<List<Reservation>>>() {
        @Override
        public Observable<List<Reservation>> call(List<Reservation> reservations) {
            List<List<Reservation>> allDays = new ArrayList<>();
            List<Reservation> singleDay = new ArrayList<>();
            Reservation lastReservation = null;
            for (Reservation reservation : reservations) {
                if (differentDays(reservation, lastReservation)) {
                    allDays.add(singleDay);
                    singleDay = new ArrayList<>();
                }
                singleDay.add(reservation);
                lastReservation = reservation;
            }
            return Observable.from(allDays);
        }
    })
    .subscribe(new Action1<List<Reservation>>() {
        @Override
        public void call(List<Reservation> oneDaysReservations) {
            // You will get each days reservations, in order, in here to do with as you please.
        }
    });

The differentDays method I leave as an exercise for the reader.

like image 132
Adam S Avatar answered Dec 17 '22 05:12

Adam S


Since you already have the complete list of reservations (i.e. a List<Reservation>, not Observable<Reservation>), you don't really need RxJava here -- you can do what you need with Java 8 stream/collections API:

Map<Calendar, List<Reservation>> grouped = reservations
    .stream()
    .collect(Collectors.groupingBy(x -> {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(x.time);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal;
    }));

As you can see, all it does is groupingBy by day of year. If your initial data would use Calendar instead of long for the timestamp, this would've looked even simpler, something like:

Map<Calendar, List<Reservation>> grouped = reservations
    .stream()
    .collect(Collectors.groupingBy(x -> x.time.get(Calendar.DAY_OF_YEAR)));
like image 34
MisterMetaphor Avatar answered Dec 17 '22 06:12

MisterMetaphor