Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return a `Comparator` from another function

Firstly, please let me clear that I'm limited by the API design so please don't change the API,however, private functions can be added.

public class Point implements Comparable<Point> {

    public Point(int x, int y)              // constructs the point (x, y)
    public void draw()                      // draws this point
    public void drawTo(Point that)          // draws the line segment from this point to that point
    public String toString()                // string representation

    public int compareTo(Point that)        // compare two points by y-coordinates, breaking ties by x-coordinates
    public double slopeTo(Point that)       // the slope between this point and that point
    public Comparator<Point> slopeOrder()   // compare two points by slopes they make with this point
}

The problem arises when I try to override the compare function in the slopeOrder() method. I tried to call the compare() method in the slopeOrder() function but since I don't have any parameters in the API I couldn't.

Please suggest some solutions to return a Comparator<Point> from the slopeOrder() method.

like image 557
Vivek Shankar Avatar asked Sep 24 '16 14:09

Vivek Shankar


People also ask

How do I return Comparator?

The compare MethodIt returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned. By overriding compare( ), you can alter the way that objects are ordered. For example, to sort in a reverse order, you can create a comparator that reverses the outcome of a comparison.

What is the return type of Comparator in Java?

compare. Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

Can we use compareTo in Comparator?

Java provides Comparable interface which should be implemented by any custom class if we want to use Arrays or Collections sorting methods. The Comparable interface has compareTo(T obj) method which is used by sorting methods, you can check any Wrapper, String or Date class to confirm this.


2 Answers

Since the description of the slopeOrder() method is:

compare two points by slopes they make with this point

That means you need to compare the values returned by calling slopeTo(Point that) on each object. Given that the return value of that method is a double, it means that you need to call Double.compare().

In pre-Java 8, you'd implement it using an anonymous class:

public Comparator<Point> slopeOrder() {
    return new Comparator<Point>() {
        @Override
        public int compare(Point o1, Point o2) {
            return Double.compare(slopeTo(o1), slopeTo(o2));
        }
    };
}

In Java 8, that's much simpler to write as a lambda expression:

public Comparator<Point> slopeOrder() {
    return (o1, o2) -> Double.compare(slopeTo(o1), slopeTo(o2));
}

Or using a method reference:

public Comparator<Point> slopeOrder() {
    return Comparator.comparingDouble(this::slopeTo);
}

In all cases, the slopeTo() calls are made on the this object of the slopeOrder() call.

like image 121
Andreas Avatar answered Sep 22 '22 13:09

Andreas


You can instantiate a Comparator<...> using a lambda expression:

public Comparator<Point> slopeOrder() {
    return (a, b) -> {
        // code here
    };
}

Here, a and b are the points to be compared.

Or if you're below java 8, you'd have to use an anonymous class:

public Comparator<Point> slopeOrder() {
    return new Comparator<Point>() {
        @Override
        public int compare(Point a, Point b) {
            // code here
        }
    };
}

If the Comparator is statless, you could create 1 instance and save it as a static final field, and just always return that instance.

Of course you can also take the long way around and create a new class that implement Comparator<Point>, and instantiate that class instead.

like image 23
Jorn Vernee Avatar answered Sep 24 '22 13:09

Jorn Vernee