Компаратор с двойным типом - PullRequest
38 голосов
/ 22 ноября 2010

Я написал следующий код:

public class NewClass2 implements Comparator<Point>
{
    public int compare(Point p1, Point p2)
    {
        return (int)(p1.getY() - p2.getY());
    }
}

Если, скажем, есть два двойных числа, 3.2 - 3.1, разница должна быть 0.1.Однако, когда я приводю число к целому числу, разница заканчивается как 0, что неверно.

Поэтому мне нужно compare(), чтобы вернуть значение типа double, а не int.Проблема в том, что мое поле getX является двойным.Как я могу решить эту проблему?

Ответы [ 9 ]

99 голосов
/ 22 ноября 2010

Я предлагаю вам использовать встроенный метод Double.compare ().Если вам нужен диапазон для совпадения двойных значений, вы можете сначала использовать chcek.

return Double.compare(p1.getY(), p2.gety());

или

if(Math.abs(p1.getY()-p2.getY()) < ERR) return 0;    
return Double.compare(p1.getY(), p2.gety());

Проблема с использованием <и> заключается в том, что NaN вернетfalse в обоих случаях, что может привести к несовместимости.например, NaN определяется как не равный чему-либо, даже сам по себе, однако в решениях @ suihock и @ Martinho, если любое из значений равно NaN, метод будет возвращать 0 каждый раз, подразумевая, что NaN равен всем.

66 голосов
/ 22 ноября 2010

Вам не нужно возвращать double.

Интерфейс Comparator используется для установления порядка сравниваемых элементов. Наличие полей, которые используют double, не имеет отношения к этому порядку.

Ваш код в порядке.

Извините, я ошибся, перечитал вопрос снова, вот что вам нужно:

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;
    }    
}
12 голосов
/ 13 декабря 2016

Начиная с Java 1.8 вы также можете использовать

Comparator.comparingDouble(p -> p.getY())
8 голосов
/ 22 ноября 2010

Метод compare должен возвращать int. Это число, которое либо:

  • Меньше , чем ноль, если первое значение меньше , чем второе;
  • равно нулю, если два значения равны ;
  • Больше , чем ноль, если первое значение на больше , чем второе;

Вам не нужно , чтобы вернуть double. Вы должны вернуть int для реализации интерфейса Comparator. Вы просто должны вернуть правильный int, в соответствии с правилами, изложенными выше.

Вы не можете просто привести из int, так как, как вы сказали, разница в 0,1 приведет к 0. Вы можете просто сделать это:

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

Но так как сравнение значений с плавающей точкой всегда проблематично, вы должны сравнить в определенном диапазоне (см. этот вопрос ), что-то вроде этого:

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;
}
3 голосов
/ 28 июня 2018

Это так удобно в Java 8, выбирайте кого угодно, как вам хочется:

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);
3 голосов
/ 01 марта 2016

Я просто хочу расширить ответ Питера Лоури на JDK 8, если вы сделаете это так:

public class NewClass2 implements Comparator<Point> {
    public int compare(Point p1, Point p2) {
        return Double.compare(p1.getY(), p2.gety());
    }    
}

Вы можете довольно легко определить этот компаратор, используя лямбда-выражение

(Point p1,Point p2) -> Double.compare(p1.getY(), p2.gety())  

Еще лучше, вы можете использовать ссылку на член, например:

Double::compare
1 голос
/ 08 мая 2017

Используйте Double.compare(/**double value 1*/, /**double value 2*/); с новым компаратором для двойного значения класса вашей модели.

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;
    }
0 голосов
/ 29 января 2018
Double min  = Arrays.stream(myArray).min(Double::compare).get();
0 голосов
/ 17 мая 2014

Ну, вы могли бы умножить эти двойные значения на соответствующий коэффициент, прежде чем конвертировать в целое число, например. в вашем случае, поскольку это только один десятичный знак, поэтому 10 будет хорошим фактором;

return (int)(p1.getY()*10 - p2.getY()*10);
...