Reduce custom object using RxJava

98
June 29, 2022, at 07:40 AM

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.

Answer 1

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());
}
Answer 2

You can use the map() method to convert the values of an Observable<List<Point>> to values for an Observable<Double>. The code can look like this:

public static void main(String[] args) throws Exception {
    Point a = new Point(45, 32);
    Point b = new Point(56, 75);
    Point c = new Point(44, 53);
    Point d = new Point(42, 54);
    Point e = new Point(42, 55);
    
    List<Point> points = new ArrayList<Point>();
    points.add(a);
    points.add(b);
    points.add(c);
    points.add(d);
    points.add(e);
    
    Subject<List<Point>> subjectOfListOfPoints = PublishSubject.create();
    
    Observable<List<Point>> observable = subjectOfListOfPoints;
    
    Observable<Double> doubleObservable = observable.map(it -> { 
        return calculateSumOfDistances(it); });
    
    doubleObservable.subscribe(it -> {
        System.out.println("The sum is: "+it);
    });
    
    subjectOfListOfPoints.onNext(points);
}
private static double calculateSumOfDistances(List<Point> points) {
    List<Double> distances = new ArrayList<Double>();
    for (int i=0; i<points.size()-1; i++) {
        double distance = distance(points.get(i), points.get(i+1));
        System.out.println("Distance is: "+distance);
        distances.add(distance);
    }
    double sum = 0;
    for (Double d: distances) {
        sum += d;
    }
    return sum;
}
private static double distance(Point a, Point b) {
    return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

This will create the following output:

Distance is: 44.384682042344295
Distance is: 25.059928172283335
Distance is: 2.23606797749979
Distance is: 1.0
The sum is: 72.68067819212742
Rent Charter Buses Company
READ ALSO
Provide streaming API endpoint as event-stream or ndjson?

Provide streaming API endpoint as event-stream or ndjson?

Spring offers at least 2 possibilities to provide a streaming api response, which are very similar

112
Maximum sum in array given constraints

Maximum sum in array given constraints

Given an array of positive integers, return the maximum sum

88
How can I remove a parameter from a subclass constructor in Java?

How can I remove a parameter from a subclass constructor in Java?

In my superclass, I have defined the parameters a, b, c and dFor its subclass, I want to remove d

77
Problem with concurrent sessions and OAuth2 in Spring Boot

Problem with concurrent sessions and OAuth2 in Spring Boot

I'm working with Spring Security 56

105