Comparator with double type

JavaCastingDoubleComparator

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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;
    }    
}

Solution 3 - Java

Since Java 1.8 you can also use

Comparator.comparingDouble(p -> p.getY())

Solution 4 - Java

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;
}

Solution 5 - Java

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);

Solution 6 - Java

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

Solution 7 - Java

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;
    }

Solution 8 - Java

int compare(Double first, Double second) {
    if (Math.abs(first - second) < 1E-6) {
        return 0;
    } else {
        return Double.compare(first, second);
    }
}

Solution 9 - Java

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);

Solution 10 - Java

Double min  = Arrays.stream(myArray).min(Double::compare).get();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser472221View Question on Stackoverflow
Solution 1 - JavaPeter LawreyView Answer on Stackoverflow
Solution 2 - JavadteohView Answer on Stackoverflow
Solution 3 - JavaJan DolejsiView Answer on Stackoverflow
Solution 4 - JavaR. Martinho FernandesView Answer on Stackoverflow
Solution 5 - JavaQM.pyView Answer on Stackoverflow
Solution 6 - JavaMiguel DurazoView Answer on Stackoverflow
Solution 7 - JavaReady AndroidView Answer on Stackoverflow
Solution 8 - JavacringineerView Answer on Stackoverflow
Solution 9 - JavaHasnainMamdaniView Answer on Stackoverflow
Solution 10 - JavaStan SokolovView Answer on Stackoverflow