El método de comparación de arreglos viola su error de contrato general en Java

Mehvish Ashiq 15 febrero 2024
  1. Diferencia entre las interfaces Comparador y Comparable
  2. Reglas de comparación para Comparador y Comparable
  3. Código Java Tener el método de comparación viola su contrato general Error
  4. Soluciones Java utilizando las interfaces Comparator y Comparable
El método de comparación de arreglos viola su error de contrato general en Java

Hoy, aprenderemos sobre las reglas de comparación utilizadas por las interfaces Comparator y Comparable, lo que conducirá a las posibles causas del error el método de comparación viola su contrato general en Java. Después de eso, entenderemos dos soluciones usando las interfaces Comparador y Comparable.

Diferencia entre las interfaces Comparador y Comparable

Estas son dos interfaces en las bibliotecas principales de Java. El Comparador es una función que compara dos objetos diferentes y es independiente de todo lo demás.

Solo busca sus dos entradas, continúa su proceso con ellas y presenta los resultados.

Por otro lado, el Comparable es una interfaz que mezclamos con una clase de datos. Por ejemplo, tenemos una clase con algunos datos; la interfaz Comparable se utilizará para comparar el primer objeto de esta clase con el segundo objeto de la misma clase.

Significa que la interfaz Comparable indica que esta instancia se puede comparar con otra instancia de la misma clase. Recuerde, el Comparable define el orden natural para la clase.

En otros aspectos, también es una función de comparación al igual que el Comparador y tiene las mismas reglas para el valor devuelto, transitivo, reflexivo, etc.

Reglas de comparación para Comparador y Comparable

El método de comparación viola su contrato general significa que el Comparador o Comparable (según lo que estemos usando) tiene un error y viola una de las reglas de consistencia. ¿Cuáles son las reglas de coherencia?

Aprendamos a continuación.

Suponemos que hemos escrito nuestro programa Java para valores de tipo entero. Por lo tanto, nuestra función de comparación debe cumplir con las siguientes reglas.

  • Dados dos números enteros a y b cualesquiera, se debe cumplir la Ley de la Tricotomía, lo que significa que se debe cumplir exactamente una de las siguientes relaciones:

    • a es menor que b (devuelve el valor -ve si a < b)
    • a es igual a b (devuelve 0 si a == b )
    • a es mayor que b (devuelve valor +ve si a > b)
  • Debe satisfacer la Transitividad, es decir, si a < b y b < c entonces, para cualesquiera tres números a, b, c, implica a < c.

  • La tercera regla es sobre Antisimetría, donde a < b implica ~b < a

  • La sustituibilidad es también una regla de comparación que dice, supongamos, a == b y a < c; esto implica b < c.

  • La última regla de comparación es la Reflexividad, donde a == a; también ~a < a.

Si se viola alguna de estas reglas, obtenemos el error que dice que el método de comparación viola su contrato general. Aprendamos con la ayuda de un ejemplo de código a continuación.

Código Java Tener el método de comparación viola su contrato general Error

Código de ejemplo:

// 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

En este código, estamos generando algunos números aleatorios usando la instancia ints de la clase Random, que se usa para generar el flujo de números aleatorios.

Para este código, si ordenamos como list.sort((a, b) -> a - b); entonces, no podremos identificar cuál es el problema y dónde está ocurriendo. Por eso lo estamos ordenando mediante logging, que nos ayudará a identificarlo.

Nos da un error, pero también proporciona muchas comparaciones de números. No discutiremos todos, pero algunos de ellos son suficientes para encontrar el error.

PRODUCCIÓN:

corregir el método de comparación viola su error de contrato general en java - error

Como podemos ver, el programa viola aquí la regla de coherencia, lo que genera este error. En la siguiente sección, tengamos la solución usando Comparador y Comparable.

Soluciones Java utilizando las interfaces Comparator y Comparable

Usemos la interfaz Comparador con menos números aleatorios.

Código de ejemplo:

// 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

Este código se ejecuta con éxito. No estamos revisando todas las comparaciones, pero veremos algunas de ellas para confirmar.

Verifique la siguiente captura de pantalla.

PRODUCCIÓN:

corregir el método de comparación viola su error de contrato general en java - solución 1

Aprendamos sobre el código Java sin errores usando la interfaz Comparable para hacer comparaciones. Para usar esta interfaz, tenemos que crear una clase que contenga datos.

Hagámoslo a continuación.

Código de ejemplo (clase 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;
    }
  }
}

Código de ejemplo (clase 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));
  }
}

Producción :

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

En este código, comparamos el recuento de letras de firstName si el lastName de dos objetos es el mismo.

Como podemos ver, los resultados son consistentes. Si a==b, a<b y a>b, devuelve 0, -1 y 1, respectivamente.

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

Artículo relacionado - Java Error