比较方法违反了其一般合同例外

时间:2016-04-13 04:58:58

标签: java collections comparator

我已检查发生此异常的原因。你能指导我吗?我在下面的代码块中做错了什么?

        Collections.sort(discountGroupDetailList, new Comparator<DiscountGroupDetail>() {
            long bdsIdOne;
            long bdsIdTwo;

            public int compare(DiscountGroupDetail discountGroupDetailOne, DiscountGroupDetail discountGroupDetailTwo) {
                boolean discOne;
                boolean discTwo;
                SimpleDateFormat DATE_FORMATER = new SimpleDateFormat("yyyy/MM/dd");
                int compVal = 0;
                discOne = discountGroupDetailOne != null && discountGroupDetailOne.getServiceId() != null
                        && discountGroupDetailOne.getServiceId().getCodeAndVersion() != null
                        && discountGroupDetailOne.getServiceId().getCodeAndVersion().getCodeDetail() != null
                        && discountGroupDetailOne.getServiceId().getCodeAndVersion().getCodeDetail().getCode() != null;

                discTwo = discountGroupDetailTwo != null && discountGroupDetailTwo.getServiceId() != null
                        && discountGroupDetailTwo.getServiceId().getCodeAndVersion() != null
                        && discountGroupDetailTwo.getServiceId().getCodeAndVersion().getCodeDetail() != null
                        && discountGroupDetailTwo.getServiceId().getCodeAndVersion().getCodeDetail().getCode() != null;

                if (discOne == true && discTwo == true) {
                    bdsIdOne = MessageBuilderHelper.getBaseDiscountServiceById(discountGroupDetailOne.getServiceId())
                            .getBdsIdNbr();

                    bdsIdTwo = MessageBuilderHelper.getBaseDiscountServiceById(discountGroupDetailTwo.getServiceId())
                            .getBdsIdNbr();
                    compVal = (int) (bdsIdOne - bdsIdTwo);
                }



                DateRange dateRangeOne = discountGroupDetailOne != null ? discountGroupDetailOne.getDateSegment() : null;
                DateRange dateRangeTwo = discountGroupDetailTwo != null ? discountGroupDetailTwo.getDateSegment() : null;

                if (compVal == 0 && dateRangeOne != null && dateRangeTwo != null) {

                    Date date = new Date();
                    compVal = DATE_FORMATER.format(date.parse(dateRangeOne.getStartDate())).compareTo(
                            DATE_FORMATER.format(date.parse(dateRangeTwo.getStartDate())));
                }

                DiscountCode discountTypeOne = (discountGroupDetailOne != null && discountGroupDetailOne
                        .getVolumeDiscountGroupDetail() != null) ? DiscountCode.getDiscount(discountGroupDetailOne
                        .getVolumeDiscountGroupDetail().getType()) : null;
                DiscountCode discountTypeTwo = (discountGroupDetailTwo != null && discountGroupDetailTwo
                        .getVolumeDiscountGroupDetail() != null) ? DiscountCode.getDiscount(discountGroupDetailTwo
                        .getVolumeDiscountGroupDetail().getType()) : null;

                boolean isFXG = ("FXG".equals(discountGroupDetailOne.getServiceGeography()) || (discountGroupDetailOne
                        .getServiceId() != null && "FXG".equals(discountGroupDetailOne.getServiceId().getOperatingCompany())))
                        && ("FXG".equals(discountGroupDetailTwo.getServiceGeography()) || (discountGroupDetailTwo
                                .getServiceId() != null && "FXG".equals(discountGroupDetailTwo.getServiceId()
                                .getOperatingCompany())));

                if (compVal == 0 && discountTypeOne != null && discountTypeTwo != null && isFXG) {
                    compVal = ((int) (Integer.parseInt(discountTypeOne.getDiscountID()) - Integer.parseInt(discountTypeTwo
                            .getDiscountID())));
                }

                return compVal;
            }
        });
    }

2 个答案:

答案 0 :(得分:3)

@immibis在我可以之前发现了答案。概括原则:假设您正在编写一个比较多对键的比较器。你想比较第一对,然后如果那不能给你一个&lt;或者&gt;回答,比较第二对,如果你还没有&lt;或&gt;,比较第三对,依此类推。

此处的规则是,在比较第一对之后,除非第一对中的键相等,否则您可能不会继续使用第二对。在你的情况下,如果两者都有“代码”并且代码相等,或者如果它们 null ,则它们是相等的。如果只有一个代码为空,那么你的错误就是继续下一对。在这种情况下,他们并不相同。我猜你的想法是,如果一个项目没有代码,你就无法比较代码。 但你必须。您需要判断没有代码的项目是否小于具有代码的项目(或大于;它取决于您希望如何在排序的数组中看到它们);并且你必须检查它,并且如果左项具有空代码则返回(例如)负数,如果右项具有空代码则返回正数。

然后你需要对日期范围做同样的事情;如果一个参数具有日期范围而另一个参数没有,则它们不相等,您必须返回一个负数或正数,而不是继续进行第三个键。

答案 1 :(得分:1)

这几乎总是由于您的比较器不是传递的或不是非对称的。对于传递性,给定三个DiscountGroupDetail个对象abc,如果a位于b之前且b位于c之前{1}},然后一般合同要求a在所有情况下都在c之前。同样,如果a等于bb等于c,则a等于c。对于不对称,交换不返回a的两个对象b0的比较顺序必须返回相反符号的数字。

鉴于你的复杂逻辑,我很难准确确定出错的地方,但以上是你需要检查的内容。