Почему результат SortBy Values ​​неверный? - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь отсортировать список по offerValues методом compareTo. Он работает нормально, так как offerValue представляет собой одну цифру, например 8.00, но если offerValue равно 20.00 или 15.00, он рассматривает их как 2 (для 20.00) и 1 (для 15.00). Не понимаю.

Comparator<OfferVO> comparatorAsc = (o1, o2) -> {
    if (o1.getOfferValue() == null && o2.getOfferValue() == null) {
        return 0;
    } else if (o1.getOfferValue() != null) {
        return o1.getOfferValue().compareTo(o2.getOfferValue());
    } else {
        return -1;
    }
};

Collections.sort(offersList, comparatorAsc);

OfferVO.class:

public class OfferVO extends OfferBaseVO implements Serializable {

    private static final long serialVersionUID = 1L;
    private String offerValue;

    public String getOfferValue() {
        return offerValue;
    }
    public void setOfferValue(String offerValue) {
        this.offerValue = offerValue;
    }
}

Выходная выборка:

"offerValue": "5.00",
"offerValue": "3.00",
"offerValue": "3.00",
"offerValue": "20.00",
"offerValue": "15.00",
"offerValue": "15.00",

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

1) Чтобы сравнить строку как числовое значение, преобразуйте их в числа в компараторе, так как String.compare() зависит от лексикографического порядка.

2) Обратите внимание, что ваш компаратор не симметричен.

Спецификация Comparator.compare() гласит:

Разработчик должен убедиться, что sgn (сравнить (x, y)) == -sgn (сравнить (y, х)) для всех х и у.

Здесь:

else if (o1.getOfferValue() != null) {
                    return o1.getOfferValue().compareTo(o2.getOfferValue());
 }

Вы полагаетесь на ненулевое значение только o1.getOfferValue() для сравнения двух объектов:

Чтобы написать более точное числовое сравнение о округлении, вы должны использовать эпсилон при сравнении плавающих значений, таких как

float epsilon = 0.0001F;
if (o1.getOfferValue() == null && o2.getOfferValue() == null){
    return 0;
} else if (o1.getOfferValue() != null && o2.getOfferValue() != null) {
    return Math.abs(Float.valueOf(o1.getOfferValue()) - Float.valueOf(o2.getOfferValue())) < epsilon)
}
 // TODO 
 // as last you have to decide here how to sort if only one of the value is not null

Если при сравнении округление не является проблемой, достаточно: Float.compare():

if (o1.getOfferValue() == null && o2.getOfferValue() == null){
    return 0;
} else if (o1.getOfferValue() != null && o2.getOfferValue() != null) {
    return Float.compare(Float.valueOf(o1.getOfferValue()), Float.valueOf(o2.getOfferValue());
}
0 голосов
/ 28 июня 2018

Используется ниже код:

Comparator<OfferVO> comparatorDesc = (o1, o2) -> {
                if (o1.getOfferValue() == null && o2.getOfferValue() == null) {
                    return 0;
                } else if (o2.getOfferValue() != null) {
                    return 
    Double.valueOf(o2.getOfferValue()).compareTo(Double.valueOf(o1.getOfferValue()));
                } else {
                    return -1;
                }
            };
0 голосов
/ 28 июня 2018

Строки сравниваются в лексикографическом (в разговорном алфавитном порядке), а не численно. Это означает, что "10" будет предшествовать "2" и так далее. Если вы хотите сравнить числовые значения, вам нужно проанализировать строки в числа, например, с помощью Double.valueOf().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...