Usar Comparable para comparar objetos y ordenarlos en un TreeMap

No puedo entender cómo el orden natural de la clase debe ser "coherente con iguales" al implementar la interfaz Comparable . Detecté una falla en mi programa y, por lo tanto, la verifiqué en la documentación de la interfaz Comparable . Mi problema es que, aunque dos objetos se consideran distintos en la base del método igual, la estructura TreeMap los trata como iguales y, en consecuencia, no acepta la segunda inserción. El código de muestra es:

public class Car  implements Comparable<Car> {

 int weight;
 String name;

public Car(int w, String n) {
    weight=w;
    name=n;
}

public boolean equals(Object o){
    if(o instanceof Car){
        Car d = (Car)o;
        return ((d.name.equals(name)) && (d.weight==weight));
    }
    return false;

}

public int hashCode(){
    return weight/2 + 17;
}

public String toString(){
    return "I am " +name+ " !!!";
}


public int compareTo(Car d){
    if(this.weight>d.weight)
        return 1;
    else if(this.weight<d.weight)
        return -1;
    else
        return 0;
}

/*public int compareTo(Car d){
    return this.name.compareTo(d.name);
}*/

}



public static void main(String[] args) {
    Car d1 = new Car(100, "a");
    Car d2 = new Car(110, "b");
    Car d3 = new Car(110, "c");
    Car d4 = new Car(100, "a");

    Map<Car, Integer> m = new HashMap<Car, Integer>();
    m.put(d1, 1);
    m.put(d2, 2);
    m.put(d3, 3);
    m.put(d4, 16);

    for(Map.Entry<Car, Integer> me : m.entrySet())
    System.out.println(me.getKey().toString() + " " +me.getValue());

    TreeMap<Car, Integer> tm = new TreeMap<Car, Integer>(m);
    System.out.println("After Sorting: ");
    for(Map.Entry<Car, Integer> me : tm.entrySet())
        System.out.println(me.getKey().toString() + " " +me.getValue());
}

El resultado es:

I am a !!! 16

I am c !!! 3

I am b !!! 2

After Sorting: 

I am a !!! 16

I am c !!! 2

Es decir, que el objeto c ha reemplazado (algo) al objeto b. Si comento el método de igualdad original y descomento el segundo método de igualdad, que compara los objetos según el nombre, el resultado es el esperado:

I am a !!! 16

I am c !!! 3

I am b !!! 2

After Sorting: 

I am a !!! 16

I am b !!! 2

I am c !!! 3

¿Por qué aparece de esta manera y qué debo alterar para insertar y ordenar diferentes objetos con algunos atributos de igual valor en un TreeMap?

Respuesta 1

Cuando los dos pesos son iguales, compareTo()debe examinar los nombres:

public int compareTo(Car d){
    if(this.weight>d.weight)
        return 1;
    else if(this.weight<d.weight)
        return -1;
    return this.name.compareTo(d.name);
}

Esto hará que sea compareTo()coherente con equals()(el último ahora puede reescribirse en términos del primero). Además, el mapa permitirá múltiples entradas con el mismo peso, siempre que los nombres difieran.

Respuesta: 2

Su compareTo()método no es consistente conequals() :

si y solo si c.compare(e1, e2)==0tiene el mismo valor booleano que e1.equals(e2)para cada e1y e2[...].

Intenta esto en su lugar:

public int compareTo(Car d){
    if(this.weight>d.weight)
        return 1;
    else if(this.weight<d.weight)
        return -1;
    else
        return this.name.compareTo(d.name);
}

En su implementación original, dos objetos se consideran iguales en términos de comparación cuando tienen el mismo weightpero diferente name, mientras que son diferentes en términos de equals().

Respuesta: 3

Tengo una cadena como String s = "hello.are..you"; Prueba de cadena [] = s.split ("\\."); La prueba [] incluye 4 elementos: hola ¿Cómo generar tres elementos no vacíos usando split ()?

Estoy tratando de crear una aplicación web, que utilizará una interfaz js e invocará Spring WS en el backend. Digamos que este es un tipo de sitio web de compras. Entonces, podría tener servicios como ...

Para este sencillo programa ... import java.lang.String; prueba de clase pública {public static void main (String [] argv) {String s = "Hello <BSLASH>"; Cadena sReplaced = s ....

Al convertir la imagen usando UploadedFile uf; // como un paremeter en function; Objeto PrimeFaces; BufferedImage old = ImageIO.read (uf.getInputstream ()); ByteArrayOutputStream temp = nuevo ...