2012-02-28 20 views
20

Otrzymuję "metodę porównania narusza jej ogólny kontrakt" po skompilowaniu kodu Java w języku Java 7, a następnie uruchomieniu go.Metoda porównania narusza ogólne warunki umowy w języku Java 7

Przeczytałem Comparison method violates its general contract! Java 7 only i zdałem sobie sprawę, że coś jest nie tak z moim kodem, który został zignorowany w poprzednich wersjach Javy. Jednak nie mogę wyliczyć, co jest nie tak z moim kodem. Funkcja Collections.sort() generuje błąd.

Mój kod to:

public Comparator sortBySmoothDays() { 
    Comparator c = new Comparator() { 
     public int compare(Object arg0, Object arg1) { 
      Date date0 = ((PosObject)arg0).getDate(); 
      Date date1 = ((PosObject)arg1).getDate(); 

      double d1 = MyUtils.calcSmoothDays(date0, new Date()); 
      double d2 = MyUtils.calcSmoothDays(date1, new Date()); 
      if (d1 >= d2) { 
       return 1; 
      } 
      else { 
       return -1; 
      } 
     } 
    }; 
    return c; 
} 


Comparator c = ComparatorUtils.getInstance().sortBySmoothDays(); 
Collections.sort(posList, c); 

Czy ktoś może pomóc? Dziękuję Ci!

+0

JFI: Rzucanie ten wyjątek to nowa funkcja Java7. Stare zachowanie można skonfigurować za pomocą nowej właściwości systemowej: java.util.Arrays.useLegacyMergeSort Zobacz http://stackoverflow.com/a/8417446/450812 – alfonx

Odpowiedz

31

Komparator musi zwracać 0 jeśli wartości są równe. W bieżącej implementacji zwracasz 1, jeśli są równe. Najprostszym sposobem, aby porównać swoje wartości double poprawnie jest wywołanie Double.compare:

double d1 = MyUtils.calcSmoothDays(date0, new Date()); 
double d2 = MyUtils.calcSmoothDays(date1, new Date()); 

return Double.compare(d1, d2); 
+0

Dziękuję bardzo! – gordon613

+0

Powoduje zwrócenie wartości 1, a nie -1. – xehpuk

+0

@xehpuk Masz rację. Naprawiłem to. –

19

Za pomocą komparatora każdy obiekt porównuje większy od siebie: zawsze zwraca jeden.

Narusza następujące requirement:

implementor musi zapewnić, że SGN (porównanie (x, y)) == -sgn (Porównaj (y, x)) dla wszystkich x i y.

Powyższe wymaganie oznacza, że ​​ musi zwrócić zero.

Polecam lekturę contract i upewnię się, że realizacja go spełnia.

W szczególności, jeśli date0.equals(date1), komparator prawdopodobnie powinien zwrócić zero natychmiast, bez wykonywania żadnych konwersji zmiennoprzecinkowych i porównań.

+0

Ogólnie rzecz biorąc, żadne dwa obiekty nigdy nie mogą być równe sobie nawzajem za pomocą tej metody . Nie ma ścieżki kodu, która daje wynik równy 0 (lub równy). –

+0

Dziękuję bardzo! – gordon613

3

Czy problem polegający na tym, że dwa porównywane obiekty, np. CalcSmoothDays, zwraca tę samą wartość, to można mieć sytuację, w której można również porównać (object1, object2) == 1 i compare (object2, object1) == 1?

Więc to oznacza, że ​​object1> Celem 2 i object2> przedmiot 1 ...

Powiązane problemy