Comparator with double type
I have written the following code:
public class NewClass2 implements Comparator<Point>
{
public int compare(Point p1, Point p2)
{
return (int)(p1.getY() - p2.getY());
}
}
开发者_开发技巧
If I let's say have two double numbers, 3.2 - 3.1
, the difference should be 0.1
. When I cast the number to an int, however, the difference ends up as 0
, which is not correct.
I therefore need compare()
to return a double, not an int. The problem is, my getX
field is a double. How can I solve this problem?
I suggest you use the builtin method Double.compare(). If you need a range for double values to be equal you can use chcek for that first.
return Double.compare(p1.getY(), p2.gety());
or
if(Math.abs(p1.getY()-p2.getY()) < ERR) return 0;
return Double.compare(p1.getY(), p2.gety());
The problem with using < and > is that NaN will return false in both cases resulting in a possibly inconsistent handling. e.g. NaN is defined as not being equal to anything, even itself however in @suihock's and @Martinho's solutions, if either value is NaN the method will return 0 everytime, implying that NaN is equal to everything.
You don't need to return double
.
The Comparator
interface is used to establish an ordering for the elements being compared. Having fields that use double
is irrelevant to this ordering.
Your code is fine.
Sorry, I was wrong, reading the question again, this is what you need:
public class NewClass2 implements Comparator<Point> {
public int compare(Point p1, Point p2) {
if (p1.getY() < p2.getY()) return -1;
if (p1.getY() > p2.getY()) return 1;
return 0;
}
}
Since Java 1.8 you can also use
Comparator.comparingDouble(p -> p.getY())
The method compare
should return an int
. It is a number that is either:
- Less than zero, if the first value is less than the second;
- Equal to zero, if the two values are equal;
- Greater than zero, if the first value is greater than the second;
You don't need to return a double
. You must return an int
to implement the Comparator
interface. You just have to return the correct int
, according to the rules I outlined above.
You can't simply cast from int, as, like you said, a difference of 0.1 will result in 0. You can simply do this:
public int compare(Point p1, Point p2)
{
double delta= p1.getY() - p2.getY();
if(delta > 0) return 1;
if(delta < 0) return -1;
return 0;
}
But since comparison of floating-point values is always troublesome, you should compare within a certain range (see this question), something like this:
public int compare(Point p1, Point p2)
{
double delta = p1.getY() - p2.getY();
if(delta > 0.00001) return 1;
if(delta < -0.00001) return -1;
return 0;
}
I just want to expand on Peter Lawrey answer on JDK 8, if you do it like this:
public class NewClass2 implements Comparator<Point> {
public int compare(Point p1, Point p2) {
return Double.compare(p1.getY(), p2.gety());
}
}
You could define this comparator using a lambda expression pretty easily
(Point p1,Point p2) -> Double.compare(p1.getY(), p2.gety())
Better yet, you could use a member reference like this:
Double::compare
It is so convinent in Java 8, choose anyone just as you wish:
Comparator<someClass> cp = (a, b) -> Double.compare(a.getScore(), b.getScore());
Comparator<someClass> cp = Comparator.comparing(someClass::getScore);
Comparator<someClass> cp = Comparator.comparingDouble(someClass::getScore);
int compare(Double first, Double second) {
if (Math.abs(first - second) < 1E-6) {
return 0;
} else {
return Double.compare(first, second);
}
}
Use Double.compare(/**double value 1*/, /**double value 2*/);
with a new Comparator for your model class double value.
public static List<MyModel> sortByDouble(List<MyModel> modelList) {
Collections.sort(modelList, new Comparator<MyModel>() {
@Override
public int compare(MyModels1, MyModels2) {
double s1Distance = Double.parseDouble(!TextUtils.isEmpty(s1.distance) ? s1.distance : "0");
double s2Distance = Double.parseDouble(!TextUtils.isEmpty(s2.distance) ? s2.distance : "0");
return Double.compare(s1Distance, s2Distance);
}
});
return modelList;
}
Well, you could multiply those double values by an appropriate factor before converting into integer, for eg. in your case since its only one decimal place so 10 would be a good factor;
return (int)(p1.getY()*10 - p2.getY()*10);
Double min = Arrays.stream(myArray).min(Double::compare).get();
精彩评论