Java Integer compareTo () – ¿por qué usar comparación vs. resta?

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.

Ver también

  • Puzzle de rompecabezas de Java 65: una saga extraña de tipo sospechoso

    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 de int . 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 .

  • La primera versión CompareTo devuelve uno de tres valores posibles: -1, 0 o 1.
  • Si reemplaza la última línea con resta, el resultado puede ser cualquier valor entero.

Si sabe que no habrá desbordamiento, podría usar algo como esto:

 public int compareTo(Integer anotherInteger) { return sign(this.value - anotherInteger.valuel); }