Java Ошибка: java .lang.IllegalArgumentException: метод сравнения нарушает его общий контракт - PullRequest
1 голос
/ 10 февраля 2020

Я работаю над старым приложением, которое изначально было написано в Java 6 и которое было обновлено до Java 7 пару лет go.

В этом приложении я использую коллекцию Collection.Sort для сортировки списка с помощью пользовательского метода compare путем реализации интерфейса Comparator. Типами объектов в списке являются CompanySchedule, которые имеют 3 свойства companyName, Schedule и expirationdate.

Список может содержать несколько объектов с одинаковым companyName, но с уникальной датой истечения срока действия. Ниже функция сравнения сортирует список в порядке возрастания companyName и с тем же списком companyName в порядке убывания срока годности. Ниже приведена реализация метода.

    public int compare(CompanySchedule c1, CompanySchedule c2) {
        int returnVal = 0;
        int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
        if (value == 0){
            if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
                returnVal = -1;
            }
            else{
                int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
                if (chkdate == 0){
                    returnVal = 0;
                }
                else if (chkdate > 0){
                    returnVal = -1;
                }
                else if (chkdate < 0){
                    returnVal = 1;
                }
            }
        }
        else if (value < 0){
            returnVal = -1;
        }
        else if (value > 0){
            returnVal = 1;
        }


        return returnVal;
    }

Я знаю, что когда транзитивное свойство не встречается в реализации метода сравнения, выше будет выдана ошибка java.lang.IllegalArgumentException: Comparison method violates its general contract.

может кто-то помочь определить, где этот метод будет нарушает переходное свойство. Спасибо за помощь.

1 Ответ

1 голос
/ 10 февраля 2020

Я думаю, что здесь есть одна проблема:

if (c1.getUseExpirationDate() == null || c2.getUseExpirationDate() == null){
                returnVal = -1;
}

Если a.getUseExpirationDate () == null, а также b.getUseExpirationDate () == null, вы получите, что a . Это нарушает последовательность. В этом методе может быть больше проблем, но я не проверил все это.

Удачи.

EDIT

Как насчет этого кода?

public int compare(CompanySchedule c1, CompanySchedule c2) {
        int returnVal = 0;
        int value = c1.getCompany().getName().compareTo(c2.getCompany().getName());
        if (value == 0) {
            if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() != null) {
                returnVal = -1;
            } else if (c1.getUseExpirationDate() != null && c2.getUseExpirationDate() == null) {
                returnVal = 1;
            } else if (c1.getUseExpirationDate() == null && c2.getUseExpirationDate() == null) {
                returnVal = 0;
            } else {
                int chkdate = c1.getUseExpirationDate().compareTo(c2.getUseExpirationDate());
                if (chkdate == 0) {
                    returnVal = 0;
                } else if (chkdate > 0) {
                    returnVal = -1;
                } else if (chkdate < 0) {
                    returnVal = 1;
                }
            }
        } else if (value < 0) {
            returnVal = -1;
        } else if (value > 0) {
            returnVal = 1;
        }


        return returnVal;
    }

Я пытался не слишком сильно его менять, для сопоставимости, но это следует изменить. В основном это определяет, что значения NULL меньше, чем другие значения.

...