Descubrí que la implementación de java.lang.Integer
del método compareTo
se ve de la siguiente manera:
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é usar comparación en lugar de resta.
return thisVal - anotherVal;
Esto se debe a un desbordamiento de enteros. Cuando thisVal
es muy grande y anotherVal
es negativo, al restar el último del anterior se obtiene un resultado que es más grande que thisVal
que puede desbordarse al rango negativo.
El “truco” de 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
, aún a - b
es positivo.
NO use este modismo. No funciona
Además, incluso si funciona , NO proporcionará ninguna mejora significativa en el rendimiento, y de hecho puede costar legibilidad.
Este rompecabezas tiene varias lecciones. El más específico es: No use un comparador basado en sustracciones a menos que esté seguro de que la diferencia entre los valores nunca será mayor que
Integer.MAX_VALUE
. En general, tenga cuidado con el desbordamiento deint
. 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 lo demuestre necesario.
Simplemente hablando, el tipo int
no es lo suficientemente grande como para almacenar la diferencia entre dos valores int
arbitrarios. Por ejemplo, la diferencia entre 1.500 millones y -1.500 millones es de 3.000 millones, pero int
no puede contener valores superiores a 2.100 millones.
Tal vez es para evitar el desbordamiento / subdesbordamiento.
Además del desbordamiento, debe tener en cuenta que la versión con sustracción no da los mismos resultados .
Si sabe que no habrá desbordamiento, podría usar algo como esto:
public int compareTo(Integer anotherInteger) { return sign(this.value - anotherInteger.valuel); }