'Java sorting list of array vs sorting list of list
I have a list of points where each point is a tiny list of size 2. I want to sort the list of points in increasing order of x and if x values are equal, I break tie by sorting in decreasing order of y.
I wrote a custom comparator to sort the points like this:
Collections.sort(points, (a, b) -> {
if (a.get(0) != b.get(0)) {
return a.get(0) - b.get(0);
} return b.get(1) - a.get(1);
});
Here's the input before sorting:
(2, 1000)
(9, -1000)
(3, 15)
(9, -15)
(5, 12)
(12, -12)
(5, 10)
(10001, -10)
(19, 8)
(10001, -8)
Here's the result produced after sorting with the above comparator:
(2, 1000)
(3, 15)
(5, 12)
(5, 10)
(9, -15)
(9, -1000)
(12, -12)
(19, 8)
(10001, -10)
(10001, -8)
Observations:
- The input is sorted in ascending order on
x. (5, 12)was correctly put before(5, 10).(9, -15)was correctly put before(9, -1000).- However,
(10001, -10)was put before(10001, -8). Even though-8is larger than-10.
Feel like I am missing something trivial. I experimented with a few other ways of writing the comparator like using Integer.compare(a, b) or just a.compareTo(t), but got the same result.
Finally, I changed the representation of point from List<Integer> to int[] and wrote the same comparator again. See results below:
Collections.sort(points, (a, b) -> {
if (a[0] != b[0])
return a[0] - b[0];
return b[1] - a[1];
});
Input before sorting:
(2, 1000)
(9, -1000)
(3, 15)
(9, -150
(5, 12)
(12, -12)
(5, 10)
(10001, -10)
(19, 8)
(10001, -8)
After sorting:
(2, 1000)
(3, 15)
(5, 12)
(5, 10)
(9, -15)
(9, -1000)
(12, -12)
(19, 8)
(10001, -8)
(10001, -10)
So list of arrays is getting sorted correctly as (10001, -8) was correctly put before (10001, -10).
I am not able to understand why changing the representation of point resolved the issue and hence this question. I can give more details on how I am creating the List of points if required.
Solution 1:[1]
@Alexander Ivanchenko explains very well why you are seeing the behavior you do. One solution to the problem is to use Integer.compareTo():
Collections.sort(points, (a, b) -> {
int xCompare = a[0].compareTo(b[0];
if (xCompare != 0) {
return xCompare;
}
retirm a[1].compareTo(b[1];
});
Beyond this, I suggest creating a Point class:
class Point {
public int x;
public int y;
}
Here I use public fields to follow the struct pattern. If you want to add getters and setters and other behavior, feel free to do so. Using a class to represent the structure of your data makes the code more understandable and easier to maintain. In fact, you can easily implement Comparable on a Point or a Comparator<Point> class.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
