Descubrí que la java.lang.Integer
implementación del compareTo
método 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 la comparación en lugar de la resta:
return thisVal - anotherVal;
java
optimization
integer
comparison
integer-overflow
Vladimir
fuente
fuente
Integer.compare(thisVal, anotherVal)
lugar de escribir la expresión ternaria.Respuestas:
Esto se debe al desbordamiento de enteros. Cuando
thisVal
es muy grande yanotherVal
es negativo, restar el último del primero da un resultado que es mayor que elthisVal
que puede desbordar al rango negativo.fuente
thisVal
no necesita ser grande.thisVal
podría ser incluso cero yanotherVal
serInteger.MIN_VALUE
y ya tiene un desbordamiento. Y tenga en cuenta que, por supuesto, también podría ser al revés,thisValue
muy pequeño yanotherVal
bastante grande, para tener una distancia que desborde elint
rango de valores.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
todavíaa - 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 la legibilidad.
Ver también
fuente
((long)a - b)
debería funcionar. Aunque tienes razón; rara vez es útil.((long)a - b)
no ayuda, ya que tienes que devolver el resultado aint
, ya que eso es lo que el comparador tiene que devolver, terminando nuevamente con un desbordamiento. Tendría que hacer algo comoLong.signum
en el resultado, que es fácil de olvidar, como muestra su comentario. Y puede que ni siquiera sea más eficiente queInteger.compare
, lo que la JVM podría manejar intrínsecamente…Simplemente hablando, el
int
tipo no es lo suficientemente grande para almacenar la diferencia entre dosint
valores arbitrarios . Por ejemplo, la diferencia entre 1.500 millones y -1.500 millones es de 3.000 millones, peroint
no puede contener valores superiores a 2.100 millones.fuente
Quizás sea para evitar desbordes / subdesbordamientos.
fuente
Además del desbordamiento, debes tener en cuenta que la versión con sustracción no da los mismos resultados .
Si sabe que no habrá desbordamiento, puede usar algo como esto:
public int compareTo(Integer anotherInteger) { return sign(this.value - anotherInteger.valuel); }
fuente
compareTo
solo se requiere para devolver un valor negativo, cero o un valor positivo, según el orden de clasificación dethis
y el otro objeto. Ver java.sun.com/j2se/1.5.0/docs/api/java/lang/…