Java Integer compareTo(): ¿por qué utilizar la comparación frente a la resta?
Descubrí que java.lang.Integer
la implementación del compareTo
método tiene el siguiente aspecto:
public int compareTo(Integer anotherInteger) {
int thisVal = this.value;
int anotherVal = anotherInteger.value;
return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
La pregunta es por qué utilizar la comparación en lugar de la resta:
return thisVal - anotherVal;
Esto se debe al desbordamiento de enteros. Cuando thisVal
es muy grande y anotherVal
negativo, restar este último del primero produce un resultado mayor que thisVal
el cual puede desbordarse al rango negativo.
¡¡¡El "truco" de la resta para comparar dos valores numéricos está roto!!!
int a = -2000000000;
int b = 2000000000;
System.out.println(a - b);
// prints "294967296"
Aquí, a < b
sin embargo, a - b
es positivo.
NO uses este modismo. No funciona.
Además, incluso si funciona , NO proporcionará ninguna mejora significativa en el rendimiento y, de hecho, puede costar la legibilidad.
Ver también
- Java Puzzlers Puzzle 65: Una extraña saga de tipo sospechoso
Este rompecabezas tiene varias lecciones. La más específica es: No utilices un comparador basado en restas a menos que estés seguro de que la diferencia entre valores nunca será mayor que
Integer.MAX_VALUE
. En términos más generales, tenga cuidado con elint
desbordamiento. Otra lección es que debes evitar el código "inteligente". Esfuércese por escribir código claro y correcto y no lo optimice a menos que sea necesario.
En pocas palabras, el int
tipo no es lo suficientemente grande como para almacenar la diferencia entre dos int
valores arbitrarios. Por ejemplo, la diferencia entre 1.500 millones y -1.500 millones es 3.000 millones, pero int
no puede contener valores superiores a 2.100 millones.
Quizás sea para evitar el desbordamiento o el desbordamiento.
Además de lo del desbordamiento, debes tener en cuenta que la versión con resta no da los mismos resultados .
- La primera versión compareTo devuelve uno de tres valores posibles: -1, 0 o 1.
- Si reemplaza la última línea con una resta, el resultado puede ser cualquier valor entero.
Si sabes que no habrá desbordamiento, puedes usar algo como esto:
public int compareTo(Integer anotherInteger) {
return sign(this.value - anotherInteger.valuel);
}