2014-01-07 3 views
3
public static Comparator<Container> DEPARTURE = new Comparator<Container>() { 
    @Override 
    public int compare(Container container1, Container container2) { 
     if (container1.departure.time.isBefore(container2.departure.time)) 
      return -1; 
     else if (container1.departure.time.equals(container2.departure.time) && 
       container1.departure.maxDuration == container2.departure.maxDuration && 
       container1.departure.transportCompany.equals(container2.departure.transportCompany) && 
       container1.departure.transportType == container2.departure.transportType) 
      return 0; 
     else 
      return +1; 
    } 
}; 

переменная вылета просто экземпляр объекта, содержащий следующие поля:Почему мой метод сравнения нарушает общий контракт?

public DateTime time; 
    public int maxDuration; 
    public TransportType transportType; 
    public String transportCompany; 

P.S. объект времени является экземпляром DateTime из библиотеки Joda-Time, а TransportType - это перечисление, содержащее константы Train, Seaship, Barge и Truck.

EDIT:

Ok, поэтому я отредактировал мой компаратор на следующее:

public static Comparator<Container> DEPARTURE = new Comparator<Container>() { 
     @Override 
     public int compare(Container container1, Container container2) { 
      if (container1.departure.time.isBefore(container2.departure.time)) 
       return -1; 
      else if (container1.departure.time.isBefore(container2.departure.time)) 
       return +1; 
      else { 
       if (container1.departure.maxDuration == container2.departure.maxDuration && container1.departure.transportType == container2.departure.transportType && container1.departure.transportCompany.equals(container2.departure.transportCompany)) 
        return 0; 
       else 
        return +1; 
      } 
     } 
    }; 

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

EDIT: РЕШЕНИЕ

Спасибо всем за ответ на мой вопрос! Изучив ваши комментарии, я придумал следующее решение, которое, похоже, работает (не тщательно протестировано):

Я фактически переместил часть сравнения в отставку своего класса, потому что мне также нужно сравнить по прибытии. Я решил просто сортировать по всем признакам (последовательно время, maxDuration, transportCompany и transportType) и решение, которое я придумал это:

public static Comparator<Container> ARRIVAL = new Comparator<Container>() { 
     @Override 
     public int compare(Container container1, Container container2) { 
      return container1.arrival.compareTo(container2.arrival); 
     } 
    }; 

    public static Comparator<Container> DEPARTURE = new Comparator<Container>() { 
     @Override 
     public int compare(Container container1, Container container2) { 
      return container1.departure.compareTo(container2.departure); 
     } 
    }; 

, а затем метод CompareTo:

@Override 
    public int compareTo(LocationMovement lm) { 
     if (this.time.isBefore(lm.time)) 
      return -1; 
     else if (this.time.isAfter(lm.time)) 
      return +1; 
     else { 
      int c = this.maxDuration - lm.maxDuration; 
      if (c != 0) return c; 

      c = this.transportCompany.compareTo(lm.transportCompany); 
      if (c != 0) return c; 

      c = this.transportType.ordinal() - lm.transportType.ordinal(); 
      return c; 
     } 
    } 
+1

Если контейнер 'c1' и контейнер' c2' имеют тот же 'departure.time', но различаются по другим признакам, то оба' сравнить (c1, c2) и 'сравнения (c2, c1) 'будет возвращать' + 1'. –

+0

Sidenote: Имея такую ​​огромную чудовищную оценку в 'else if', просто спрашивает о проблемах. –

+0

Спасибо, ребята, за ответ. Не могли бы вы взглянуть на мое редактирование, пожалуйста? – Yaeger

ответ

1

Для того, чтобы реализовать compare, все, что вы проверяете, должно иметь понятие «меньше», «больше» или «равно» друг другу, а затем вы должны решить порядок их проверки , возвращая меньше/больше для первого из элементов, которые не равны. Таким образом, вы удовлетворяете контракт, что compare(a, b) должен быть обратным compare(b, a). Если все части того, что вы сравниваете, не имеют понятия «больше» или «меньше» (например, тип транспорта), то либо вы не можете реализовать compare, либо вы должны вынудить произвольное (но надежное) большая/меньшая интерпретация.

Вот концептуальный пример этого. В этом случае заказ, который я выбрал (произвольно), это: время, продолжительность, компания и тип. Но другой порядок может быть более разумным. Это просто пример. Кроме того, вы не сказали, что такое тип transportType, поэтому я предположил, что он имеет метод compareTo; очевидно, это не так, и вам, возможно, придется это подкорректировать.

public static Comparator<Container> DEPARTURE = new Comparator<Container>() { 
    @Override 
    public int compare(Container container1, Container container2) { 
     int rv; 

     // Times 
     rv = container1.departure.time.compareTo(container2.departure.time); 
     if (rv == 0) { 
      // Duration 
      if (container1.departure.maxDuration < container2.departure.maxDuration) { 
       rv = -1; 
      } 
      else if (container1.departure.maxDuration > container2.departure.maxDuration) { 
       rv = 1; 
      } 
      else { 
       // Transport company 
       rv = container1.departure.transportCompany.compareTo(container2.departure.transportCompany); 
       if (rv == 0) { 
        // Transport type 
        rv = container1.departure.transportType.compareTo(container2.departure.transportType); 
       } 
      } 
     } 
     return rv; 
    } 
}; 
+0

Спасибо, что ответили, я редактировал мой вопрос, содержащий мое решение. – Yaeger

4

генподряда что

COMPARATOR.compare(a, b) = - COMPARATOR.compare(b, a) 

В вашем случае код, который возвращает -1 в одну сторону, может вернуть 0 другой.

+0

Я вижу, как его исходный код вернет ** '1' ** в одном направлении, но' 0' в другой, но не как он может вернуть '-1' и' 0'. Неважно, конечно, проблема одна и та же. –

0

Обратите внимание, что, если два контейнера c1 и c2 имеют равную departure.time, но различаются по другим признакам, то оба compare(c1, c2) и compare(c2, c1) будет возвращать +1, т.е. c1>c2 и c2>c1.

Вместо этого вы должны либо полностью отбросить другие поля, либо сравнить их отдельно в вложенных или последовательных if-else с в случае, если время отправления равно.

Посмотрите на этот answer to a related question на чистый способ сравнения объектов по нескольким атрибутам.

Смежные вопросы