Java 为什么SortBy值的结果是错误的?

Java 为什么SortBy值的结果是错误的?,java,collections,Java,Collections,我正在尝试使用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()

我正在尝试使用
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);
输出样本:

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",
字符串是(通俗地说是字母顺序),而不是数字。这意味着
“10”
将位于
“2”
之前,依此类推。如果要比较数值,需要将字符串解析为数字,例如。

字符串是(按字母顺序),而不是数字。这意味着
“10”
将位于
“2”
之前,依此类推。如果要比较数值,则需要将字符串解析为数字,例如。

1)要将字符串作为数值进行比较,请在比较器中将其转换为数字作为
字符串。compare()
依赖于字典顺序

2) 请注意,比较器不是对称的

Comparator.compare()
规范规定:

实现者必须确保sgn(compare(x,y))==-sgn(compare(y, x) )适用于所有x和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
1) 若要将字符串作为数值进行比较,请在比较器中将它们转换为数字作为
String。compare()
依赖于字典顺序

2) 请注意,比较器不是对称的

Comparator.compare()
规范规定:

实现者必须确保sgn(compare(x,y))==-sgn(compare(y, x) )适用于所有x和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
使用以下代码:

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;
                }
            };
比较器比较器Desc=(o1,o2)->{ if(o1.getOfferValue()==null&&o2.getOfferValue()==null){ 返回0; }else if(o2.getOfferValue()!=null){ 返回 Double.valueOf(o2.getOfferValue()).compareTo(Double.valueOf(o1.getOfferValue()); }否则{ 返回-1; } };
使用以下代码:

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;
                }
            };
比较器比较器Desc=(o1,o2)->{ if(o1.getOfferValue()==null&&o2.getOfferValue()==null){ 返回0; }else if(o2.getOfferValue()!=null){ 返回 Double.valueOf(o2.getOfferValue()).compareTo(Double.valueOf(o1.getOfferValue()); }否则{ 返回-1; } };

猜测一下,
getOfferValue
返回的是一个
字符串
,但是没有更多的上下文,这只是猜测而已。我们需要查看
OfferVO的代码
您可以共享OfferVO代码和您添加的OfferVO类的输出吗?您想用数字进行比较,但可以使用字符串存储您的数字。字符串按字典顺序排序。使用适当的类型(数字:double或BigDecimal)存储数值。据猜测,
getOfferValue
正在返回一个
字符串,但没有更多上下文,这只是一个猜测,我们需要查看OfferVO的代码。您是否可以共享OfferVO代码和您获得的输出?您添加了OfferVO类,您希望进行数字比较,但您使用字符串存储您的数字。字符串按字典顺序排序。使用适当的类型(数字:double或BigDecimal)存储数值。
Math.abs(Float.valueOf(o1.getOfferValue())-Float.valueOf(o2.getOfferValue())
非常难看。为什么不使用
Float。而使用进行比较?@ortis它不是强制性的。它是为了防止舍入误差。我更新了。您可以使用
新的BigDecimal(o.getOfferValue())
(JB Nizet在对问题的评论中提到)来防止舍入错误。这将提供数字的全部精度。@davidxx不应该是Float.valueOf(o1.getOfferValue()).compareTo(Float.valueOf(o2.getOfferValue));事实上我把两者都混在一起了<代码>浮动。compareTo(浮动)将需要一个不必要的装箱浮动。由于前面选中了null,
Float.compare(Float,Float)
很好。
Math.abs(Float.valueOf(o1.getOfferValue())-Float.valueOf(o2.getOfferValue())
非常难看。为什么不使用Float。而使用进行比较?@ortis它不是强制性的。它是为了防止舍入误差。我更新了。您可以使用
新的BigDecimal(o.getOfferValue())
(JB Nizet在对问题的评论中提到)来防止舍入错误。这将提供数字的全部精度。@davidxx不应该是Float.valueOf(o1.getOfferValue()).compareTo(Float.valueOf(o2.getOfferValue));事实上我把两者都混在一起了<代码>浮动。compareTo(浮动)将需要一个不必要的装箱浮动。由于前面选中了null,
Float.compare(Float,Float)
可以。