Machen Sie niemals subtraktionsbasierte Komparatoren

  • Tutorial
Mir ist aufgefallen, dass Menschen, wenn sie ihren Komparator schreiben, sehr oft Zahlen vergleichen, um ihre Subtraktion zu bevorzugen. Dieser Ansatz ist prägnant und prägnant, funktioniert jedoch leider nicht immer richtig und kann daher nicht verwendet werden. Ich selbst bin einmal darauf gestoßen, und ich sehe es so oft, dass ich beschlossen habe, eine Notiz zu schreiben.

Betrachten Sie den folgenden Code:

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Collections;
import java.util.List;
import static java.util.Arrays.*;
import static org.testng.Assert.assertEquals;
public class ComparatorAlgTest {
    List list1, list2;
    @BeforeMethod
    public void init(){
        list1 = asList(1,2);
        list2 = asList(Integer.MIN_VALUE, Integer.MAX_VALUE);
    }
    void check(String name){
        System.out.println(name+" list1 = " + list1);
        System.out.println(name+" list2 = " + list2);
        assertEquals(list1, asList(1,2) );
        assertEquals(list2, asList(Integer.MIN_VALUE, Integer.MAX_VALUE) );
    }
    @Test
    public void testWrong() {
        Collections.sort(list1, (Integer a, Integer b) -> a-b );
        Collections.sort(list2, (Integer a, Integer b) -> a-b );
        check("wrong");
    }
    @Test
    public void testFine() {
        Collections.sort(list1, (Integer a, Integer b) -> a.equals(b)? 0: a>b ? 1:-1 );
        Collections.sort(list2, (Integer a, Integer b) -> a.equals(b)? 0: a>b ? 1:-1 );
        check("fine");
    }
}


Wenn Sie dies ausführen, können Sie sehen, dass testWrong () fehlschlägt, und anstatt in aufsteigender Reihenfolge zu sortieren, wird manchmal eine Verringerung angezeigt. Tatsächlich ist ein Zahlenpaar (Integer.MIN_VALUE, Integer.MAX_VALUE) bei weitem nicht die einzige Kombination, in der ein subtraktionsgesteuerter Komparator funktioniert falsch. Damit das Ergebnis falsch ist, ist es notwendig und ausreichend, dass während der Subtraktion ein Überlauf auftritt. Sie können beispielsweise asList (-2, Integer.MAX_VALUE) ersetzen, und der subtraktionsgesteuerte Vergleich funktioniert auch nicht.

fine list1 = [1, 2]
fine list2 = [-2147483648, 2147483647]
wrong list1 = [1, 2]
wrong list2 = [2147483647, -2147483648]



Jetzt auch beliebt: