javarx-javareactivex

Reduce custom object using RxJava


I'm using RxJava, I have a list of Point and i want to calculate the distance between each point and get the sum.

The point class look like this

public class Point {
    public double x;
    public double y;
}

So i need to map and reduce at same time, but i didn't found a solution.

public Observable<Double> totalDistance(Observable<List<Point>> obs) {
 return obs.reduceMap(new ArrayList<Integer>, (list, pointA, pointB) -> distance(pointA, pointB)). ?
}

What its the most efficient way to do it (or at least a solution that works) ? Which operator should i use ?

To give a more concrete example, here is what I have and what I want:

Point a (45, 32)
Point b (56, 75)
Point c (44, 53)
Point d (42, 54)
Point e (42, 55)

a to b = 10m
b to c = 15m
c to d = 25m
d to e = 10m

Result = 60m

In reality my points are GPS positions and I use the haversine formula to calculate the distance between two positions.

I use observables because the list of points to be calculated is updated sometime. In fact every x points the user has reached, I have an instruction to send. After sending the instruction, a new list of points until the next instruction is emit.


Solution

  • You can try buffer and reduce operators. For example:

    public Observable<Double> totalDistance(Observable<List<Point>> obs) {
        return obs.flatMap(points ->
                Observable.fromIterable(points)
                        .buffer(2 /* count */, 1 /* skip */)
                        /* this emits a list of each two adjacent points from a given list of points. */
                        .reduce(0.0  /* initial value */, (totalDistance, twoPoints) -> {
                                    // note: calculation may be skipped if the twoPoints list contains less than
                                    // two elements.
                                    final Point pointA = twoPoints.get(0);
                                    final Point pointB = twoPoints.get(1);
                                    return totalDistance + distance(pointA, pointB);
                                }
                        ).toObservable());
    }