Estoy resolviendo un problema. Tengo que crear un TreeSet de objetos de empleados personalizados donde los datos deben ordenarse por salario, pero la identificación del empleado debe ser única. Entiendo que los métodos equals() y hashCode() no funcionan para TreeSet y necesitamos escribir nuestro objeto son iguales o no lógicos dentro del método compareTo(). Estoy comprobando si ambos ID de empleado son iguales y luego devuelven 0, lo que significa que no se debe agregar el objeto.
Pero el resultado no es el deseado, ya que también se están agregando empleados con la misma identificación de empleado. Traté de depurar esto pero no obtengo la respuesta correcta.
Este es el código.
public class Employee implements Comparable<Employee>{ int empId; String empName; double salary; public Employee() { super(); } public Employee(int empId, String empName, double salary) { super(); this.empId = empId; this.empName = empName; this.salary = salary; } @Override public int hashCode() { return empId; } @Override public boolean equals(Object o) { if(this == o) return true; if(o == null || this.getClass() != o.getClass()) return false; Employee e = (Employee) o; return (this.empId == e.empId); } @Override public String toString() { return empId + " " + empName + " " + salary; } @Override public int compareTo(Employee e) { if(empId == e.empId) return 0; if(this.salary < e.salary) { return -1; } else { return 1; } } }El principal método de programa.
public static void main(String[] args) { TreeSet<Employee> eSet = new TreeSet<>(); eSet.add(new Employee(1, "john", 20000)); eSet.add(new Employee(2, "jim", 10000)); eSet.add(new Employee(9, "mike", 50000)); eSet.add(new Employee(3, "jack", 30000)); eSet.add(new Employee(3, "david", 40000)); eSet.add(new Employee(9, "liam", 80000)); eSet.add(new Employee(9, "brad", 89000)); eSet.add(new Employee(3, "jason", 85000)); eSet.add(new Employee(2, "ted", 35000)); for(Employee e: eSet) { System.out.println(e); } }La salida del programa anterior sale como
2 jim 10000.0 1 john 20000.0 3 jack 30000.0 2 ted 35000.0 9 mike 50000.0 3 jason 85000.0Aquí, como puede ver, los empleados con la misma identificación de empleado se agregan al TreeSet, lo que no debería suceder. Si estoy usando un HashSet, el problema se resuelve, pero tengo que implementarlo usando TreeSet para obtener el comportamiento ordenado.
¿Puede alguien por favor guiarme dónde me estoy equivocando?
La implementación de Comparable viola el contrato de Comparable::compareTo , en particular esta parte:
Finalmente, el implementador debe asegurarse de que
x.compareTo(y)==0implique quesignum(x.compareTo(z)) == signum(y.compareTo(z)), para todoz.
Podemos demostrar esta violación con el siguiente código:
final Employee jim = new Employee(2, "jim", 10_000); final Employee ted = new Employee(2, "ted", 35_000); final Employee john = new Employee(9, "john", 20_000); System.out.println("jim compare to ted: " + jim.compareTo(ted)); System.out.println("john compare to jim: " + john.compareTo(jim)); System.out.println("john compare to ted: " + john.compareTo(ted));lo que lleva a la siguiente salida:
jim compare to ted: 0 john compare to jim: 1 john compare to ted: -1 Podemos solucionar este problema eliminando el salario del método compareTo y ordenando solo por empId :
@Override public int compareTo(Employee e) { return Integer.compare(empId, e.empId); }