Comparator with double type

99,101

Solution 1

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 2

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 3

Since Java 1.8 you can also use

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

Solution 4

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

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);
Share:
99,101
user472221
Author by

user472221

Updated on January 21, 2020

Comments

  • user472221
    user472221 over 4 years

    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?

  • user472221
    user472221 over 13 years
    thanks for complete answer ! I get the whole ! I never forget such a this way
  • Vishy
    Vishy over 11 years
    Java 7 added compare() for Long and Integer consistency.
  • Jerome
    Jerome over 11 years
    I think this will fail with NaN and *_INFINITY
  • robjwilkins
    robjwilkins about 8 years
    I like the use of the lambda in this answer, its a very good suggestion. I dont understand how you could use a member reference though? Could you provide an example? thanks
  • robjwilkins
    robjwilkins about 8 years
    This answer only works in certain circumstances. I.e. when multiplying by 10 will result in the double values becoming a whole number.
  • HasnainMamdani
    HasnainMamdani about 8 years
    @robjwilkins: Could you please clarify that in which case this method of choosing an appropriate factor wouldn't work?
  • robjwilkins
    robjwilkins about 8 years
    It doesnt work in the case where getY returns a number which cannot be multiplied by 10 to get an integer. For example if getY returns 3.2111 then this solution will not work. Since getY returns a double, it is entirely feasible for it to return 3.2111. This solution is therefore very limited, and there are much better alternatives.
  • HasnainMamdani
    HasnainMamdani about 8 years
    @robjwilkins In the case you mentioned the 'appropriate factor' would be 10000 and not 10. Agreed that simplicity comes with limitations and tradeoffs, therefore the user decides the most feasible approach according to the needs of his/her use case.
  • xdhmoore
    xdhmoore about 7 years
    Here is a link to the source code of Double.compare() to see how it handles NaN.
  • xdhmoore
    xdhmoore about 7 years
    You could probably also use Math.signum if you wanted slightly different behavior on NaNs.
  • Asu
    Asu over 6 years
    Note that you can revert sort order by using Double.compare(d2, d1) as opposed to Double.compare(d1, d2). Obvious but still.