Está en la página 1de 18

Ordenando Listas

Ya hemos visto en la clase anterior sobre los wrappers, que son, digamos, las
clases que absorben a los elementos primitivos, a los tipos de dato primitivo.
Y ahora vamos a volver ya a lo que es nuestro paquete Java.util propiamente
dicho, ya con nuestras listas. ¿Qué más vamos a hacer con las listas ahora?
A ver, sabemos ya que dado que la lista a veces nosotros vamos agregando los
elementos conforme van llegando, no siempre van a estar en orden, entonces
lo primero que tendremos que hacer es qué sucedería si a mí me piden ordenar
una lista. ¿De qué forma puedo ordenarla?

La azul

Lo primero que tenemos que preguntarnos aquí es qué tipo de orden


queremos. O sea, como ustedes saben, pueden ser ordenadas alfabéticamente,
dependiendo del titular, pueden ser ordenadas por quien tiene más dinero,
ordenadas por el número de cuenta, ordenadas por el número de agencia.

[03:22] Entonces tenemos muchas formas de ordenarlo. ¿Cómo le decimos


nosotros a Java "ordénalo de repente por el número de cuenta"? Antiguamente
teníamos una clase separada de las listas que era pues la clase comparator. Sí,
mira, creo que era collections.

¿Por qué? Porque es esa clase collections, muy diferente de la interfaz, ojo,
tienes la interfaz collection y la clase collections, con S. La clase collections
tenía un método que era para ordenar las listas, que el método sort. ¿Pero cuál
es el problema ahí?
[04:00] Que ya que Java es un lenguaje orientado a objetos, entonces no sería
lo más ideal que la lista tenga su propio método para ordenarse y no depender
de un objeto externo. Entonces tenemos esas dos formas, vamos a explorar la
primera, vamos a ponerle un lista, aquí un punto y vamos a escribir sort.

¿pero qué tipo de variable es? El tipo de variable que espera es cualquier cosa
que extienda de cuenta.

¿Qué significa comparator? Signo de interrogación, extends cuenta. Bueno. El


signo de interrogación extens cuenta significa, vamos a ponerlo aquí,
cualquier clase hija de cuenta o la cuenta misma, como puede ser. ¿Y qué
sería comparator? Comparator es la interfaz que va a usar.

Vemos que claro, me abre un generic aquí. Vamos a entrar a comparator para
explorarlo más. Vemos aquí que él tiene primero una notación
FunctionalIinterface que lo vamos a ver un poco más adelante. No va a
importar por ahora. Y tiene un comparator con un generic. ¿Qué significa eso?
Él va a aceptar una clase como parámetro para poder comparar.

[06:10] Y después de la documentación, todo, vemos que él tiene el método


equals. Tiene un método para hacer reversed, todo, pero el método en el que
nos vamos a concentrar va a ser en este: compare. El método con pero tiene T
01 y T02. ¿Qué significa eso? Es el mismo T que yo especifiqué aquí.

[06:34] Por lo tanto, si yo aquí le digo que esto es un comparador de cuenta,


adivinen qué vaya aquí abajo. Exacto, cuenta 1, cuenta 2. Entonces, vamos a
centrarnos aquí
Por número de cuenta para que sea un poco más auto explicativo. Aquí le voy
a dar un extends. ¿Extends quién? Comparator. ¿Comparator de quién? De
cuenta. ¿Por qué? Porque yo voy a trabajar con cuentas.

vamos a explorar un poco aquí, de qué se trata este compare. Borramos esto.

[08:30] Vemos que para comenzar, si yo quiero establecer una comparación sí


o sí, tengo que tener dos objetos, comparo esto, comparo con esto de aquí. Y
ahora, para que él compare, ¿cómo funciona en este caso el algoritmo de
comparación que quiere implementar aquí? Dado que yo quiero ordenarlo
por número de cuenta, lo que yo tendría que hacer aquí es, por ejemplo un si,
creo aquí.

Si la cuenta o1.getNumero, porque yo lo voy a comprobar por número de


cuenta, es igual a o2.getNumero de cuenta. Como este método es un int,
debería retornar un entero. Entonces aquí yo voy a retornar 0. ¿Por qué?
Porque en el algoritmo de comparación que va a usar Java, él va a funcionar
de esta forma.

[09:24] Si es que o1 es mayor a o2, entonces él va a retornar 1, positivo, si el


otro es mayor, o sea, si o1 es menor, y o2 es mayor, entonces retorna un
negativo, puede ser normalmente se usa 1 menos 1, pero puede ser cualquier
valor. Sé que ahorita les suena un poco rayado, pero ya van a ver cómoes esto.
Le decimos: si no if, le damos aquí. Perfecto. Le damos este de aquí, y aquí le
decimos, vamos a ver aquí.
[10:09] Si número de cuenta 1 es mayor a número de cuenta 2, entonces return
1, normalmente es retornar 1 o retornar cualquier entero positivo, no se
preocupen, no importa si retornas este número o si retornas 1. Finalmente else,
eso significa que el único else que puede haber, ¿qué es? De que sea menor, si
o1.getNumero es menor que 02, es la única opción que queda, entonces
retornamos -1.

[10:46] Y aquí también puede ser menos lo que ustedes quieran, no se


preocupen. Aquí vamos a retornar solamente -1 y listo. Esa es la
implementación de nuestro método compare. Ahora, ¿por qué es así, con eso
de 0, 1, -1? Yo sé que es confuso, ¿pero por qué es así? Porque el algoritmo
de Java, cuando va a implementar este compare, dependiendo si es 1 o - 1, él
va a ir ordenando por dentro los elementos.

Eso ya va a ser automáticamente ¿quién? El método compare de la interfaz


comparator. Y listo. Ahora ya tengo mi ordenador por número de cuenta.
¿Qué más necesito ahora? Ahora necesito enviarlo como parámetro. ¿Por qué?
Porque la lista me pide pues enviar como parámetro.

¿Comparator va a ser igual a quién? A new. Listo, new


OrdenadorPorNumeroCuenta. ¿Por qué? Porque él es la implementación de
esta interfaz.

[12:08] Y recuerden pues, que si recordamos nuestra clase de herencia y


polimorfismo, yo puedo especificar aquí la interfaz y aquí la implementación,
igual que aquí en nuestro caso de la lista.

Ahora qué mandamos aquí como parámetro?


Nuestro comparator. Y el código compila.

¿Cómo podemos comprobar que está bien, que el código funciona? Vamos a
hacer algo
Funiona

Usando Wrappers

ya vimos en el video anterior cómo podemos ordenar una cuenta. Ya vimos


aquí que el método sort recibe una implementación de la interfaz comparator y
para internamente ejecutar pues este método de aquí que es el compare.

Ahora, ¿qué pasaría si yo ya no deseo un orden por número de cuenta sino


deseo un orden por titular, por el nombre del cliente?
¿Qué pasaría si ahora yo quiero ordenarlo por nombre de titular? Como ya
tengo esta implementación, voy a volver a crear otra clase,
OrdenadorPorNombreTitular implements Comparator. ¿De quién? De Cuenta.

Y aquí decirle algo así pues como o1.getTitular().getNombre(), obtener el


primer dígito, el del nombre, primer dígito, no pero el primer caracter del
nombre. Ver si es mayor, menor, pero esto va a dar mucho trabajo. Entonces
recordemos. ¿Qué tengo en nombre o qué atributo, qué tipo de dato es nombre
que me podría permitir hacer algunas cosas? Tenemos que nombre es un
string.

Y ya que nombre es un string. ¿Será que string me da de repente alguna


facilidad para hacer algo con otro string, como una comparación? Es así.

Porque me dice que string tiene un método que se llama compareTo ¿y qué
recibe como parámetro compareTo. Otro string. Y entonces le digo "Okay,
vamos a implementarlo".

tenemos aquí el método compareTo y este método de aquí, compareTo de


string, ¿adivinen qué? Retorna un entero. ¿Por qué? ¿Por qué creen que
retorna un entero?

[03:55] Porque al igual que en nuestro método anterior, que usamos para
ordenar por número de cuenta, el también va a retornar o1, -1 o 0,
dependiendo del orden que salga de aquí.
Y yo, tranquilamente, podría hacer esto de aquí. Voy a borrar este return de
aquí y voy a retornar directamente este método de aquí. CompareTo, titular y
nombre, perfecto.

¿Por qué? Porque internamente, miren, la clase string ya va a hacer por mí ese
trabajo de obtener el primer carácter, compararlo con otro y retornar un
entero. Entonces, listo,

¿Qué vamos a hacer ahora? Vamos a darle, otra vez vamos a crear un
comparator de cuenta.
Pero aquí vemos que no sé si lo ordenó de verdad por nombre de titular o no,
porque yo no estoy imprimiendo el nombre de titular, así que solamente para
estar seguro voy a entrar aquí a cuenta.

Entro a mi método toString, que yo recuerdo haber implementado aquí,


perfecto. Y en toString le voy a agregar el titular. Que sería básicamente algo
así: + ", Nombre". O solamente Titular mejor, para que quede más corto. Y
aquí un + this.titular.getNombre(); Guardamos. De esta forma, yo ya voy a
imprimir el nombre de mi titular.

Nuevamente ejecuto. Y listo.

Vemos que ya lo ordenó en orden alfabético. Entonces, bueno, ya sabemos,


pues que si necesito ordenarlo y basado en el string que recibe, en la cadena
de texto, ya la clase string ya tiene ahí su método pues compareTo, que ya me
evita hacer todo ese trabajo.

Esto es igual

A esto.
Y si ustedes se han dado cuenta y han sido un poco curiosos, ya que el método
compareTo recibes solamente estos dos parámetros. Perdón, recibe este
parámetro pero es basado en esta clase de aquí, ¿será que no puedo hacer algo
parecido aquí? Porque si se dan cuenta, si el número de cuenta es igual al otro,
perfecto, retorno ese, si éste es mayor retorno 1, si no menos 1.

[07:11] Pero esto sería igual, esto sería exactamente igual a decirle que retorne
esto de aquí.

Pero esto se resume simplemente en esta operación matemática. Y de la


misma forma, por ejemplo, esta sería pues forma básica. Esta sería nuestra
forma intermedia y tenemos una forma más también que puede ser nuestra
forma wrapper. ¿Por qué? Porque en nuestro wrapper, nosotros tenemos un
método también llamado compare, y adivinen qué recibe compare: recibe un
entero X y un entero Y, que significa dos enteros.

[08:50] Por lo tanto, yo puedo hacer un compare con el primer número de


cuenta y el segundo número de cuenta.

Entonces ya vimos aquí que para ordenar podemos hacerlo, primero


implementar el algoritmo por nosotros, forma básica. Tenemos una forma
intermedia que es usando una resta en el caso de los enteros porque nos va a
dar la misma operación que como si ejecutáramos aquí

[09:54] como les dije, no necesitamos retornar o 0 o 1, - 1 si no es 0, cualquier


entero o cualquier negativo, entre lo positivo o lo negativo y tenemos una
forma usando wrappers que es ya usando el método comprar que está en
nuestra clase integer.

[10:10] Entonces yo sé que este tema de comparador, de ordenar listas, eso es


un poquito complicado al inicio, pero no se preocupen, es muy, muy sencillo.
En el siguiente video vamos a ver la forma antigua que teníamos para ordenar
nuestras listas.

Orden Natural’
Entonces si yo sé que recibo una implementación de la interfaz directamente
aquí, yo podría hacerlo también de la siguiente forma. Miren lo que yo tengo
aquí.

¿Por qué? Porque este OrdenadorPorNombreTitular está implementando mi


Comparator, por lo tanto yo puedo evitar incluso tener que instanciar una
interfaz Comparator para recién enviarla como parámetro.

Entonces esa es una de las ventajas que me permite aquí el aceptar una
interfaz funcional, recuerden aquí esta anotación, FunctionalInterface es
implementar una interfaz funcional aquí a mi método. ¿Por qué es interfaz
funcional?

[01:36] Bueno, esa es pregunta de examen de certificación.

Interfaces funcionales en Java son aquellas que tienen un solo método


para implementar. En este caso es este de aquí, el compare. Es el único
método que tenemos que implementar de esta interfaz.
Qué más vamos a hacer ahora? Ya sabemos que post Java 8, tenemos esta
forma de aquí.

¿Y si tuvieran que trabajar con un Java 7, Java 1.6? En los sistemas


bancarios aún manejan versiones antiguas de Java. Entonces tenemos que
aprender también cómo ordenarlo de esa forma, y para eso tenemos la clase
que les comenté en el primer video. Es la clase Collections con S, recuerden,
porque Collection es la interfaz.

ya tenemos aquí nuestra lista y nuestro algoritmo para ordenarla. En este caso
es la implementación de nuestro comparator. Vamos a ver si funciona.

Vemos que lo ordenó. Pero les dije que ese era un método sobrecargado. ¿Por
qué? Y aquí es donde entra lo interesante.
Y vemos que compila nivel de parámetros, pero el sort no está compilando y
aquí entra una pregunta: ¿ustedes cómo creen que el método sort puede
saber, por qué ordenarlos? Si yo aquí le digo: "Collections, ordéname está
lista".

¿Y cómo él va a saber si lo va a ordenar por nombre de titular o si lo va a


ordenar por número de cuenta? La verdad es que él no lo sabe. Y por eso es
que no está compilando, porque él te dice: "Okay, yo quiero ordenarlo, pero
no sé cómo ordenarlo".

Y aquí interviene lo que es llamado de orden natural. ¿Qué es el orden


natural? Es el atributo por defecto bajo el cual vas a ordenar una lista o un
arreglo. Vamos a ver aquí qué es lo que él dice. ¿Qué dice aquí la excepción?
Vamos a ver el método sort en el tipo de Collections no es aplicable para esta
lista. ¿Por qué? Porque yo no he definido mi orden natural.

Ahora, ¿mi orden natural en dónde debería estar definido? ¿En la lista o
en la cuenta, que es lo que voy a ordenar? Así es, en la cuenta. Porque yo
voy a ordenar cuentas dentro de esa lista, entonces lo que voy a hacer aquí es
entrar a mi clase cuenta. Y aquí existe otra interfaz que yo puedo implementar
aquí. Y esa interfaz se llama Comparable, también de Java.lang.

Recuerden Comparable no es de Java.util, es de Java.lang. Y Comparable


también acepta un generic, y adivinen, ¿generic de qué? De cuenta. Listo. Le
damos a guardar, por lo tanto, Comparable de cuenta nos va a hacer
implementar un método. Vamos a darle aquí y es el método compareTo, que
está aquí.

Este método de aquí es el que


nos está dando la interfaz Comparable. Vamos a entrar aquí solamente para
explorarlo un poco. Vemos que no es una interfaz funcional, pero aun así,
solamente tiene este método CompareTo, pero no está marcada como interfaz
funcional. ¿Por qué? Porque las interfaces funcionales salieron a partir de Java
8.

[06:46] Entonces en esta versión de aquí, en la 1.02 que salió esta interfaz, no
existía esa anotación. Lo más probable es que quizá más adelante sea
deprecada, pero hasta el momento es muy, muy utilizada y van a ver por qué.
Porque aquí en mi clase cuenta, ya que tengo mi método compareTo,
supongamos que ahora yo voy a ordenarlo por defecto. Orden natural por
Número de Agencia.

Qué
debería de hacer yo? Aquí tranquilamente, podría hacerlo de cualquiera de
estas tres formas. Es exactamente lo mismo. Es la misma implementación, la
misma lógica, puedo hacerlo con los ifs, puedo hacerlo con la resta o
directamente con el wrapper.

[07:44] En este caso personalmente, a mí me gusta más hacerlo con el


wrapper. Siento que sea un poco más elegante.

ya ordenado por número de agencia en orden


ascendente.

[09:31] Entonces ya vimos también lo que es el concepto de orden natural que


tiene pues mi cuenta en este momento, así como puede ser por número de
agencia, también podría ser de repente por saldo que yo tengo en mi cuenta. Y
para el saldo, así como Integer tiene su método compareTo, adivinen quién
más tiene su método compareTo. Orden natural: Saldo. Y adivinen quién.

[10:03] return Doble, el wrapper. Double.compare entre this.getSaldo() y


o.getSaldo(), y listo, ya tenemos ahora otro nuevo orden natural, basado ahora
en saldo. Y usando, pues, el método compare de nuestro wrapper double.
Entonces, como siempre les digo, estudien mucho esta parte de ordenar, van a
encontrar muchos ejercicios aquí en la plataforma.

[10:40] Las dudas que tengan pueden ponerlas aquí en el foro y recuerden
siempre: esta es la forma antigua de ordenar, vamos a dejarlo aquí en claro:
forma antigua. Y esta es la forma normal, digamos que se usa ahora, pero
recuerden desde Java 8. Y bueno, aquí tenemos ya cómo ordenar las cuentas.
Desde java 8 es esta

¿Será que son las únicas formas que existen de implementar estos algoritmos
o interfaces para ordenar listas? No. No son las únicas, y en la próxima clase
vamos a ver ya las tan esperadas lambdas.
Extras
Desafío de Collections

También podría gustarte