Fix-Vergleichsmethode verletzt ihren allgemeinen Vertragsfehler in Java

Mehvish Ashiq 15 Februar 2024
  1. Unterschied zwischen Komparator- und vergleichbaren Schnittstellen
  2. Vergleichsregeln für Vergleicher und Vergleichbar
  3. Java-Code mit dem Fehler Vergleichsmethode verstößt gegen ihren allgemeinen Vertrag
  4. Java-Lösungen mit den Schnittstellen Comparator und Comparable
Fix-Vergleichsmethode verletzt ihren allgemeinen Vertragsfehler in Java

Heute lernen wir die von den Schnittstellen Comparator und Comparable verwendeten Vergleichsregeln kennen, die zu möglichen Ursachen für den Fehler Vergleichsmethode verletzt seinen allgemeinen Vertrag in Java führen. Danach werden wir zwei Lösungen verstehen, die die Schnittstellen Comparator und Comparable verwenden.

Unterschied zwischen Komparator- und vergleichbaren Schnittstellen

Dies sind zwei Schnittstellen in Java-Kernbibliotheken. Der Comparator ist eine Funktion, die zwei verschiedene Objekte vergleicht und von allem anderen unabhängig ist.

Es sucht nur nach seinen beiden Eingaben, setzt seinen Prozess mit ihnen fort und präsentiert die Ergebnisse.

Andererseits ist das Comparable eine Schnittstelle, die wir mit einer Datenklasse mischen. Zum Beispiel haben wir eine Klasse mit einigen Daten; die Comparable-Schnittstelle wird verwendet, um das erste Objekt dieser Klasse mit dem zweiten Objekt derselben Klasse zu vergleichen.

Das bedeutet, dass die Schnittstelle Vergleichbar anzeigt, dass diese Instanz mit einer anderen Instanz derselben Klasse verglichen werden kann. Denken Sie daran, dass Vergleichbar die natürliche Reihenfolge für die Klasse definiert.

Ansonsten ist sie ebenso eine Vergleichsfunktion wie der Comparator und hat die gleichen Regeln für den Rückgabewert, transitiv, reflexiv usw.

Vergleichsregeln für Vergleicher und Vergleichbar

Die Vergleichsmethode verletzt ihren allgemeinen Vertrag bedeutet, dass der Vergleicher oder Vergleichbar (basierend auf dem, was wir verwenden) einen Fehler hat und gegen eine der Konsistenzregeln verstößt. Welche Konsistenzregeln gibt es?

Lassen Sie uns sie unten lernen.

Wir gehen davon aus, dass wir unser Java-Programm für ganzzahlige Werte geschrieben haben. Daher muss unsere Vergleichsfunktion die folgenden Regeln einhalten.

  • Bei zwei beliebigen ganzen Zahlen a und b muss das Trichotomiegesetz erfüllt sein, was bedeutet, dass genau eine der folgenden Beziehungen wahr sein muss:

    • a ist kleiner als b (es gibt den Wert -ve zurück, wenn a < b)
    • a ist gleich b (gibt 0 zurück, wenn a == b )
    • a ist größer als b (es gibt den Wert +ve zurück, wenn a > b)
  • Es muss die Transitivität erfüllen, was bedeutet, wenn a < b und b < c, dann impliziert es für drei beliebige Zahlen a, b, c a < c.

  • Die dritte Regel betrifft die Antisymmetrie, wobei a < b ~b < a impliziert

  • Substituierbarkeit ist auch eine Vergleichsregel, die sagt, angenommen, a == b und a < c; dies impliziert b < c.

  • Die letzte Vergleichsregel ist Reflexivität, wobei a == a; auch ~a < a.

Wird gegen eine dieser Regeln verstoßen, erhalten wir die Fehlermeldung Vergleichsmethode verstößt gegen ihren allgemeinen Vertrag. Lassen Sie es uns anhand eines Codebeispiels unten lernen.

Java-Code mit dem Fehler Vergleichsmethode verstößt gegen ihren allgemeinen Vertrag

Beispielcode:

// import libraries
import static java.util.stream.Collectors.toCollection;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

// Main
public class Main {
  public static void main(String[] args) {
    // generate random numbers
    List<Integer> list = new Random(209).ints(32L).boxed().collect(toCollection(ArrayList::new));
    // sort using lambda expression
    list.sort(logging((a, b) -> a - b));
  } // end main()

  // logging the comparisons
  static Comparator<Integer> logging(Comparator<Integer> c) {
    return (a, b) -> {
      int r = c.compare(a, b);
      System.err.printf("%,14d %,14d => %,14d\n", a, b, r);
      return r;
    };
  } // end logging()
} // end class

In diesem Code generieren wir einige Zufallszahlen, indem wir die Instanz ints der Klasse Random verwenden, die zum Generieren des Stroms von Zufallszahlen verwendet wird.

Für diesen Code sortieren wir als list.sort((a, b) -> a - b); dann können wir nicht erkennen, was das Problem ist und wo es auftritt. Deshalb sortieren wir sie via logging, was uns hilft, sie zu identifizieren.

Es gibt uns einen Fehler, aber es bietet auch viele Vergleiche von Zahlen. Wir werden nicht alle besprechen, aber einige davon reichen aus, um den Fehler zu finden.

AUSGANG:

Vergleichsmethode verstößt gegen ihren allgemeinen Vertragsfehler in Java - Fehler

Wie wir sehen können, verletzt das Programm hier die Konsistenzregel, was zu diesem Fehler führt. Lassen Sie uns im nächsten Abschnitt die Lösung mit Comparator und Comparable haben.

Java-Lösungen mit den Schnittstellen Comparator und Comparable

Verwenden wir die Comparator-Schnittstelle mit weniger Zufallszahlen.

Beispielcode:

// import libraries
import static java.util.stream.Collectors.toCollection;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;

// Main
public class Main {
  public static void main(String[] args) {
    // generate random numbers
    List<Integer> list = new Random(5).ints(32L).boxed().collect(toCollection(ArrayList::new));
    // sort using lambda expression
    list.sort(logging((a, b) -> a - b));
  } // end main()

  // logging the comparisons
  static Comparator<Integer> logging(Comparator<Integer> c) {
    return (a, b) -> {
      int r = c.compare(a, b);
      System.err.printf("%,14d %,14d => %,14d\n", a, b, r);
      return r;
    };
  } // end logging()
} // end class

Dieser Code wird erfolgreich ausgeführt. Wir gehen nicht alle Vergleiche durch, aber wir werden einige davon sehen, um sie zu bestätigen.

Überprüfen Sie den folgenden Screenshot.

AUSGANG:

Vergleichsmethode verstößt gegen allgemeinen Vertragsfehler in Java – Lösung 1

Erfahren Sie mehr über den fehlerfreien Java-Code mit der Vergleichsschnittstelle Comparable. Um diese Schnittstelle zu verwenden, müssen wir eine Klasse erstellen, die Daten enthält.

Lass es uns unten tun.

Beispielcode (Klasse Students.java):

public class Student implements Comparable<Student> {
  private String firstName;
  private String lastName;

  public Student(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int compareTo(Student other) {
    /*
    compare the last names and save the result
    in `compareResult` variable
    */
    int compareResult = this.lastName.compareTo(other.lastName);

    /*
    If both last names match, then it would be true means 0. So,
    dive into the `if` condition and check if the count of their
    first name matches.
    if this.count == other.count return 0
    if this.count > other.count return 1
    if this.count < other.count return -1
    */

    if (compareResult == 0) {
      if (this.firstName.chars().count() == other.firstName.chars().count()) {
        compareResult = 0;
        return compareResult;
      } else if (this.firstName.chars().count() > other.firstName.chars().count()) {
        compareResult = 1;
        return compareResult;
      } else {
        compareResult = -1;
        return compareResult;
      }
    } else {
      return compareResult;
    }
  }
}

Beispielcode (Klasse Main.java):

public class Main {
  public static void main(String[] args) {
    Student std1 = new Student("Mehvish", "Ashiq");
    Student std2 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 1: " + std1.compareTo(std2));

    Student std3 = new Student("Aftab", "Ashiq");
    Student std4 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 2: " + std3.compareTo(std4));

    Student std5 = new Student("Mehr-un-nissa", "Ashiq");
    Student std6 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 3: " + std5.compareTo(std6));
  }
}

AUSGANG:

Result of Comparison 1: 0
Result of Comparison 2: -1
Result of Comparison 3: 1

In diesem Code vergleichen wir die Buchstabenanzahl von firstName, wenn der lastName zweier Objekte gleich ist.

Wie wir sehen können, sind die Ergebnisse konsistent. Wenn a==b, a<b und a>b, wird jeweils 0, -1 und 1 zurückgegeben.

Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

Verwandter Artikel - Java Error