Компаратор с двойным типом
Я написал следующий код:
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
. Однако, когда я передаю число в int, разница заканчивается как 0
, что неверно.
Поэтому мне нужно compare()
вернуть double, а не int. Проблема в том, что мое поле getX
является двойным. Как я могу решить эту проблему?
Ответы
Ответ 1
Вам не нужно возвращать 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;
}
}
Ответ 2
Я предлагаю вам использовать встроенный метод 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 равно всем.
Ответ 3
Метод 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;
}
Ответ 4
Так как Java 1.8 вы также можете использовать
Comparator.comparingDouble(p -> p.getY())
Ответ 5
Я просто хочу расширить ответ Питера Лоури на 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
Ответ 6
Используйте 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;
}
Ответ 7
Ну, вы можете умножить эти двойные значения на соответствующий коэффициент перед преобразованием в целое число, например. в вашем случае с момента его единственного десятичного разряда, поэтому 10 будет хорошим фактором;
return (int)(p1.getY()*10 - p2.getY()*10);