Как решить Java Collections.sort () Метод сравнения нарушает его общий договор Исключение - PullRequest
0 голосов
/ 21 июня 2019

Я использую Collections.sort для сортировки списка в порядке возрастания на основе поля времени. Ниже приведен код

private String getShipmentInpickingTime(List<Shipments> shipments) {
        logger.info("in getShipmentInpickingTime");
        DateFormat sdf = new SimpleDateFormat("hh:mm");

        Collections.sort(shipments, (o1, o2) -> {
            try {
                if ((!"null".equals(o1.getShipmentinpickingtime())
                        && !StringUtils.isEmpty(o1.getShipmentinpickingtime()))
                        && (!"null".equals(o2.getShipmentinpickingtime())
                                && !StringUtils.isEmpty(o2.getShipmentinpickingtime()))) {
                    return sdf.parse(o1.getShipmentinpickingtime()).compareTo(sdf.parse(o2.getShipmentinpickingtime()));
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
            int count1 = 0;
            return count1;
        });

Этот метод выдает исключение -

java.lang.IllegalArgumentException: Comparison method violates its general contract.

Я прошел через гугл по этой проблеме - там говорится, что я сравниваю объект большего размера с объектом меньшего размера. Я попытался изменить последовательность объектов, но безуспешно.

Ответы [ 2 ]

1 голос
/ 23 июня 2019

Вы получаете исключение только один раз, если или элементов не удалось проанализировать.

Рассмотрим три отгрузки со следующим временем:A - 12:34Б - 34:56C - ноль

С вашим компаратором compare(A, C) вернет 0, compare(B, C) вернет 0, но compare(A, B) вернет ненулевой результат, нарушив тем самым общий контракт транзитивности.

Одним из простых подходов является использование синтаксиса Comparator.comparing для анализа каждого элемента в отдельности:

DateFormat sdf = new SimpleDateFormat("hh:mm");

shipments.sort(Comparator.comparing(
                   Shipments::getShipmentinpickingtime, 
                   Comparator.nullsLast(Comparator.comparing(time -> {
                       try {
                           if (!"null".equals(time) && !StringUtils.isEmpty(time)) {
                               return sdf.parse(time);
                           }
                       } catch (ParseException ignoe) {
                           // Not a valid time
                       }
                       return null;
                   })))
              );
0 голосов
/ 26 июня 2019

Вы не упомянули, какая строка кода вызывает эту ошибку.Я не уверен, какой StringUtils вы использовали здесь, com.sun.deploy.util.StringUtils не имеет .isEmpty() метод.Поэтому я переопределил это.

Вот рабочий код вашей проблемы:

public static void main(String[] args){
    getShipmentInpickingTime(new ArrayList<Shipments>(){{
        add(new Shipments("12:00"));
        add(new Shipments("12:03"));
        add(new Shipments("12:02"));
    }});
}

private static void getShipmentInpickingTime(List<Shipments> shipments) {
    DateFormat sdf = new SimpleDateFormat("hh:mm");

    System.out.println(shipments.toString());
    Collections.sort(shipments, (o1, o2) -> {
        try {
            if ((!"null".equals(o1.getShipmentPickingTime())
                    && !(o1.getShipmentPickingTime() == null || o1.getShipmentPickingTime().length() < 1))
                    && (!"null".equals(o2.getShipmentPickingTime())
                    && !(o2.getShipmentPickingTime() == null || o2.getShipmentPickingTime().length() < 1))) {
                return sdf.parse(o1.getShipmentPickingTime()).compareTo(sdf.parse(o2.getShipmentPickingTime()));
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    });

    System.out.println(shipments.toString());
}

Содержание класса пересылок:

public class Shipments {

    private String shipmentPickingTime;

    public Shipments(String shipmentPickingTime) {
        this.shipmentPickingTime = shipmentPickingTime;
    }

    public String getShipmentPickingTime() {
        return shipmentPickingTime;
    }

    public void setShipmentPickingTime(String shipmentPickingTime) {
        this.shipmentPickingTime = shipmentPickingTime;
    }

    @Override
    public String toString() {
        return "Shipments{" +
                "shipmentPickingTime='" + shipmentPickingTime + '\'' +
                '}';
    }
}

Вывод:

[Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:03'}, Shipments{shipmentPickingTime='12:02'}] [Shipments{shipmentPickingTime='12:00'}, Shipments{shipmentPickingTime='12:02'}, Shipments{shipmentPickingTime='12:03'}]

...