Home > Software engineering >  Reduce a list of custom objects in java
Reduce a list of custom objects in java

Time:10-03

I have two custom classes called OrthogonalPoint and PolarPoint.

public class OrthogonalPoint extends AbstractPoint<OrthogonalPoint> {
    private double x;
    private double y;

    // constructor, getters, ...
}
public class PolarPoint extends AbstractPoint<PolarPoint> {
    private double rho;
    private double theta;

    // constructor, getters, ...
}

Both extend an abstract class AbstractPoint.

public abstract class AbstractPoint<PointType extends AbstractPoint<PointType>> {

    public abstract double getX();

    public abstract double getY();

    public final double distance(PointType other) {
        // calculate distance between current point and other point
    }
}

Next, I have a class Route.

public class Route<T extends AbstractPoint<T>> {

    private final List<T> points = new ArrayList<>();

    public void appendPoint(T point) {
        this.points.add(point);
    }

    public double routeDistance() {
        // calculate total distance
    }
}

A route is an ordered number of points whose length is defined as the sum of the distances of the points in the sequence. So, if a route consists of three points (p1, p2, and p3) the distance of the route is p1.distance(p2) p2.distance(p3). In the routeDistance function, I want to calculate this distance. I have tried something like

public double routeDistance() {
    return this.points.stream().reduce(0d, (point, point2) -> point.distance(point2));
}

But the body part of the lambda function is underlined red:

Bad return type in lambda expression: double cannot be converted to T

What would be the correct way to calculate the distance? I would like to use the reduce, but any solution is appreciated.

CodePudding user response:

Your problem is that you use reduce in the wrong way. Reduce doesn’t get two elements from your stream but the current accumulator and the current element and combine them to get the new accumulator. Here is a good tutorial on reduce: https://www.baeldung.com/java-stream-reduce The easiest way here is to not use stream. As you need to keep the order of each two points, just use a regular for loop with i between 0 and n-1 to loop over all sub routes and sum the lengths.

CodePudding user response:

You can't reduce a Point to a Double. If you need to use an ArrayList then you can mapToDouble and then sum() (a special case of a reduction):

points.stream().skip(1).mapToDouble(point ->
        points.get(points.indexOf(point) - 1).distance(point)).sum();

or

points.stream().limit(points.size() - 1).mapToDouble(point ->
        point.distance(points.get(points.indexOf(point)   1))).sum();

With ÌntStream you can do:

IntStream.range(1, points.size()).mapToDouble(i ->
        points.get(i - 1).distance(points.get(i))).sum();

or

IntStream.range(0, points.size() - 1).mapToDouble(i ->
        points.get(i).distance(points.get(i   1))).sum();
  • Related