Quiero ordenar un array
de 2 dimensionales en Java acuerdo con algunas reglas, digamos que la distancia desde el origen. Vi varias maneras de hacerlo mediante Arrays.sort()
:
1) Arrays.sort(points, Comparator.comparing(p -> p[0]*p[0] + p[1]*p[1]));
2) Arrays.sort(points, (p1, p2) -> p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1]);
3) Definición de la class
:
class Point implements Comparable<Point>{
// class variables, constructor
public int compareTo(Point p) {
return (x*x + y*y).compareTo(p.x*p.x + p.y*p.y);
}
}
Una matriz pts
de tipo Points
continuación, se crea y Arrays.sort(pts)
se utiliza. Mi pregunta es con respecto a 1) y 2) : veo la diferencia entre el pero no entiendo cuándo utilizar uno y cuándo usar la otra y lo que exactamente Comparator.comparing()
está haciendo. ¿Por qué es la primera solución llevando a la información que acaba con un punto, mientras que el segundo necesidad dos puntos?
Comparator.comparing
se implementa como sigue:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
es decir, se utiliza la Function
que se pasa a ella con el fin de transformar cada uno de los elementos comparados en una Comparable
y, a continuación, utiliza el Comparable
's compareTo
método.
Cuando usted está pasando la función p -> p[0]*p[0] + p[1]*p[1]
, que está convirtiendo cada punto a su suma de los cuadrados. Entonces, cuando las Comparator
necesidades para comparar dos puntos, se compara la suma de los cuadrados de los dos puntos, que es casi equivalente al cálculo de la diferencia de las sumas de cuadrados de los dos puntos (que no es exactamente equivalente, ya que la comparación de dos números calculando su diferencia puede producir una salida errónea en caso de desbordamiento numérico).
Eso es exactamente lo que su segundo Comparator
- (p1, p2) -> p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1]
- lo hace,
puesto p1[0]*p1[0] + p1[1]*p1[1] - p2[0]*p2[0] - p2[1]*p2[1] == (p1[0]*p1[0] + p1[1]*p1[1]) - (p2[0]*p2[0] + p2[1]*p2[1])
.
El uso Comparator.comparing()
es más seguro, ya que compara las sumas de cuadrados de los dos puntos sin calcular su diferencia. Utiliza Double
Es compareTo()
lugar (suponiendo que las coordenadas de sus puntos son Double
o double
).
En otras palabras, la primera alternativa utiliza una Function
que necesita sólo un punto ya que esta función le dice Comprator.comparing
cómo transformar cada uno de los 2 puntos.
Por otro lado, la segunda alternativa acepta 2 puntos (que son los argumentos necesarios del Comparator.compare()
método) y determina el orden relativo de estos 2 puntos.