Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this @Override for Arrays.sort work in Java?

Arrays.sort(people, (n1, n2) -> (n2[0] == n1[0])?  n1[1] - n2[1] : n2[0] - n1[0]);

or

Arrays.sort(people,new Comparator<int[]>(){
    @Override
    public int compare(int[] n1, int[] n2){
        return (n2[0] == n1[0])? n1[1] - n2[1]: n2[0] - n1[0];
    }
});

Both these perform the same operation.

Input: [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]

Output: [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]

I know the code is sorting it in groups but I don't understand how. I was similarly confused about PriorityQueue in Java:

PriorityQueue<Integer> pq = new PriorityQueue<>((a, b)-> b - a);

This one sorts in decreasing order.

Can someone explain it? Where can I study or read more about these "overrides" if there is any such material?

like image 284
SUVAIN G Avatar asked Jun 09 '20 09:06

SUVAIN G


People also ask

How does Arrays sort work in Java?

sort(Object[] a, int fromIndex, int toIndex) method sorts the specified range of the specified array of objects into ascending order, according to the natural ordering of its elements. The range to be sorted extends from index fromIndex, inclusive, to index toIndex, exclusive.

How array sort works internally in Java?

Arrays. sort method provides us with a quick and simple way to sort an array of primitives or objects that implement the Comparable interface in ascending order. When sorting primitives, the Arrays. sort method uses a Dual-Pivot implementation of Quicksort.

Does Arrays sort change the original array Java?

Arrays. sort does not modify the variable, it modifies the array object the variable points to.


4 Answers

The arrow notation is a lambda function, short-hand for the same Comparator implementation. That's why you see the same results. It is not about @Override here, what you're asking for is how a Comparator works really.

A comparator orders 2 objects in the following order:

  • negative, sorts descending
  • zero, does nothing
  • pozitive, sorts ascending

So for the priority queue part, when the comparator sorts 1, 4, 6, 3, it compares the elements of the array and it swaps them if the difference is negative, e.g. it would swap 1 and 4, 4 and 6, etc.

For the first part of the question, you're using this implementation: (n2[0] == n1[0])? n1[1] - n2[1]: n2[0] - n1[0]

For 2-sized integer arrays, you're comparing the arrays as following.

  • If the first element of each array are not equal, you're trying to sort in descending order(i.e. bringing a [7, 0] ahead of a [4, 4])
  • If the first element of each array is equal, you're trying to sort in ascending order(i.e. bringing [7,0] ahead of [7,1]).
like image 103
Silviu Burcea Avatar answered Oct 21 '22 23:10

Silviu Burcea


The javadoc of Comparator method compare(T o1, T o2) says:

Returns:
a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

"Less than" and "greater than" refers to the sort order, not the numerical value, so if you want to sort descending, then 7 is "less than" 5.

So, the following shows how to sort ascending and descending:

// Ascending
(a, b) -> a - b

// Decending
(a, b) -> b - a

However, you should never use - minus operator for this, since it can cause overflow. Use the Integer.compare(int x, int y) method instead, or the equivalent methods on Long, Short, Byte, Double, and Float:

// Ascending
(a, b) -> Integer.compare(a, b)

// Decending
(a, b) -> Integer.compare(b, a)

Next part is that your code sorts by 2 fields, first field descending, second field ascending:

(o1, o2) -> {
    if (o1.a != o2.a)
        return Integer.compare(o2.a, o1.a); // sort by a (descending)
    return Integer.compare(o1.b, o2.b); // secondary sort by b (ascending)
}

Which in your code is done using a ternary operator:

(o1, o2) -> o1.a != o2.a ? Integer.compare(o2.a, o1.a) : Integer.compare(o1.b, o2.b)

Or rather the other way around:

(o1, o2) -> o1.a == o2.a ? Integer.compare(o1.b, o2.b) : Integer.compare(o2.a, o1.a)
like image 24
Andreas Avatar answered Oct 22 '22 01:10

Andreas


@Override annotation just marks when a method from subclass overrides method from superclass. In your second example you are using something called anonymous inner class, you are basically passing an instance of a class, in your example Comparator which has an abstract method called compare. You are implementing that methods functionality in place, so that you don't have to create a new class which is extending Comparator class and so on.

Your first example is basically the same as second, but its syntax is shorter to write and looks cleaner, and easier to read. The second one is called Lambda expression.

like image 1
Duško Mirković Avatar answered Oct 22 '22 00:10

Duško Mirković


Above Arrays.sort accept 2 params. The first is the list need to be sorted, the second is the Comparator. The Comparator is the functional interface that have method compare. Since it's the interface, so you need to implement it (@Override means that your implementation is overriding this method). The method compare allow you to decide the sort strategy (ascending, descending, blabla).

like image 1
SoT Avatar answered Oct 22 '22 01:10

SoT