Java Comparator Arrays.sort()

Giacomo :

I want to sort an array of 2 dimensional arrays in Java according to some rules, let's say the distance from the origin. I saw several ways of doing it using Arrays.sort():

1) Arrays.sort(points, Comparator.comparing(p -> p[0]*p[0] + p[1]*p[1]));

2) Arrays.sort(points, (p1, p2) -> p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1]);

3) Defining the class:

class Point implements Comparable<Point>{
     // class variables, constructor
     public int compareTo(Point p) {
         return (x*x + y*y).compareTo(p.x*p.x + p.y*p.y);
     }
}

An array pts of type Points is then created and Arrays.sort(pts) is used. My question is regarding 1) and 2): I see the difference between the but I do not understand when to use one and when to use the other and what exactly Comparator.comparing() is doing. Why is the first solution carrying the information just with one point while the second need two points?

Eran :

Comparator.comparing is implemented as follows:

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor)
{
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

i.e. it uses the Function you pass to it in order to transform each of the compared elements into a Comparable, and then uses the Comparable's compareTo method.

When you are passing the function p -> p[0]*p[0] + p[1]*p[1], you are converting each point to its sum of squares. Then, when the Comparator needs to compare two points, it compares the sum of squares of the two points, which is almost equivalent to computing the difference of the sums of squares of the two points (it's not exactly equivalent, since comparing two numbers by computing their difference can produce wrong output in case of numeric overflow).

That's exactly what your second Comparator - (p1, p2) -> p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1] - does,

since p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1] == (p1[0]*p1[0] + p1[1]*p1[1]) - (p2[0]*p2[0] + p2[1]*p2[1]).

Using Comparator.comparing() is safer, since it compares the sums of squares of the two points without computing their difference. It uses Double's compareTo() instead (assuming the coordinates of your points are Double or double).

In other words, the first alternative uses a Function that needs just one point since this function tells Comprator.comparing how to transform each of the 2 points.

On the other hand, the second alternative accepts 2 points (which are the required arguments of the Comparator.compare() method) and determines the relative order of these 2 points.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=307805&siteId=1