patternjavaMinor
Comparator based on Double values in Java
Viewed 0 times
javadoublebasedvaluescomparator
Problem
I have class point that represents point in 2D and I want to sort these points once based on their x-coordinate and second based on their y coordinate. Since x and y are double values my code looks like this:
Is this a good way for defining Comparator? Is there better solution for sorting based on x and on y coordinate? Is this the only way to deal with
public static class Point{
int id;
public double x;
public double y;
Point(int id, double x, double y){
this.id = id;
this.x = x;
this.y = y;
}
public static Comparator xComparator = new Comparator(){
@Override
public int compare(Point t1, Point t2) {
// TODO Auto-generated method stub
if (t1.x > t2.x){
return 1;
}
if (t1.x yComparator = new Comparator(){
public int compare(Point t1, Point t2) {
// TODO Auto-generated method stub
if (t1.x > t2.x){
return 1;
}
if (t1.x < t2.x){
return -1;
}
else{
return 0;
}
}
};
}Is this a good way for defining Comparator? Is there better solution for sorting based on x and on y coordinate? Is this the only way to deal with
compare method based on two double values?Solution
Your question does not show how you call/use the Comparators you have defined. Despite that, there are a number of issues I see with your code, and feel I should point out....
When you have data that is sorted, the data tends to last around for a while, and sorted-data is often a very important assumption for complex processing (i.e. if the data was not sorted correctly the computations will fail).
Whenever you have sorted data, and Comparable data, the data should almost always be immutable (cannot possibly change). If the data can change after the sort happens, then the sorted data is no longer sorted.
So, your Point class should probably be an immutable class. At the moment, it has a number of problems with that:
Your class should look more like:
ahhh, I see skiwi just answered a bunch... I'll cover some other stuff from here on....
Reiterating his comments:
Right, when you have value-based items like this, it is often convenient to make the Point have a 'natural' ordering. This means that the Point class should implement
Having two comparators is a problem, you only want one, that does both coordinates.
Consider a
This will be one comparator that does both axes.
Then, you can use this Point as a natural sort order, and use it as a key in a
Note, I reused the comparison function
When you have data that is sorted, the data tends to last around for a while, and sorted-data is often a very important assumption for complex processing (i.e. if the data was not sorted correctly the computations will fail).
Whenever you have sorted data, and Comparable data, the data should almost always be immutable (cannot possibly change). If the data can change after the sort happens, then the sorted data is no longer sorted.
So, your Point class should probably be an immutable class. At the moment, it has a number of problems with that:
- The member fields should be final.
- There should be 'getters' for the fields, and the fields themselves should be private (not public like you have).
Your class should look more like:
public static final class Point{
private final int id;
private final double x;
private final double y;
Point(int id, double x, double y){
this.id = id;
this.x = x;
this.y = y;
}
public int getID() {
return id;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
.....ahhh, I see skiwi just answered a bunch... I'll cover some other stuff from here on....
Reiterating his comments:
- the equals and hashCode method he suggests are very important (I was about to add that too).
Right, when you have value-based items like this, it is often convenient to make the Point have a 'natural' ordering. This means that the Point class should implement
Comparable, and then implement the compareTo(Point other) method.Having two comparators is a problem, you only want one, that does both coordinates.
Consider a
compareTo() method like:public static class Point implements Comparable {
....
public int compareTo(final Point other) {
if (other == null) {
// non null always comes after null
return 1;
}
final int xcomp = Double.compare(this.x, other.x);
return xcomp == 0 ? Double.compare(this.y, other.y) : xcomp;
}This will be one comparator that does both axes.
Then, you can use this Point as a natural sort order, and use it as a key in a
TreeMap, and or things like Arrays.sort(pointarray), etc.Note, I reused the comparison function
Double.compare() to do the heavy lifting of the compare.Code Snippets
public static final class Point{
private final int id;
private final double x;
private final double y;
Point(int id, double x, double y){
this.id = id;
this.x = x;
this.y = y;
}
public int getID() {
return id;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
.....public static class Point implements Comparable<Point> {
....
public int compareTo(final Point other) {
if (other == null) {
// non null always comes after null
return 1;
}
final int xcomp = Double.compare(this.x, other.x);
return xcomp == 0 ? Double.compare(this.y, other.y) : xcomp;
}Context
StackExchange Code Review Q#56185, answer score: 8
Revisions (0)
No revisions yet.