Ordenar ArrayList de objetos por 3 atributos

0nLy

Hola, llevo ya 2 o 3 días rallado porque no consigo ordenar un arrayList de Alumnos por 3 atributos.
Lo que quiero básicamente es ordenar el array, primero por el primer apellido, luego por el segundo apellido y finalmente por el nombre.

De momento lo único que he conseguido es ordenarlo por el primer apellido, pero no sé como añadirle al método compare que también me lo ordene por los otros 2 atributos.
A ver si me podeis echar una manita, el código que tengo es el siguiente (si necesitais la clase Alumno o cualquier cosa me decís).

Los atributos los he llamado:
apellido1, apellido2, nombre

ArrayList<Alumno> arrayAlumno = new ArrayList<>();

//Aquí hay un bucle para crear Alumnos con sus atributos que no creo que os haga falta que os lo ponga

Collections.sort(arrayAlumno, new Comparator<Alumno>() {
            @Override
            public int compare(Alumno t1, Alumno t2) {
                
return t1.getApellido1().compareTo(t2.getApellido1()); } }); for (Alumno c:arrayAlumno){ System.out.println(c); }

Mi profesora me ha dado una pista diciendome que simplemente me falta añadir "algo" al método compare, pero no tengo ni zorra idea (Estoy empezando).
gracias de antemano!

0nLy

Nada, ya lo acabo de conseguir, no sé si será más o menos chapuza (ya os digo que estoy empezando con Java).
Os dejo el código de como lo he hecho por aquí (la verdad es que no lo entiendo muy bien) y si quereis explicarmelo os lo agradecería muchísimo ^^

        Collections.sort(arrayAlumno, new Comparator<Alumno>() {
            @Override
            public int compare(Alumno a, Alumno b) {
                int resultado = a.getApellido1().compareTo(b.getApellido1());
                if (resultado != 0 ) {
                    return resultado;
                }
                resultado = a.getApellido2().compareTo(b.getApellido2());
                if (resultado != 0 ) {
                    return resultado;
                }
                resultado = a.getNombre().compareTo(b.getNombre());
                if (resultado != 0 ) {
                    return resultado;
                }
                return resultado;
            }
        });
1 respuesta
MTX_Anubis

#2 Pues es sencillo:
Primero comparas el apellido, si es igual (el resultado del compareTo es 0 cuando es igual, -1 cuando es menor y 1 cuando es mayor), comparas el segundo apellido, si el segundo apellido también es igual pues comparas el nombre.

Si quieres ahorrarte unas lineas de código puedes hacerlo así porque el ultimo checkeo es innecesario (y con un operador ternario aun te ahorrarías un par de lineas mas!)

    Collections.sort(arrayAlumno, new Comparator<Alumno>() {
                @Override
                public int compare(Alumno a, Alumno b) {
                    int resultado = a.getApellido1().compareTo(b.getApellido1());
                    if (resultado != 0 ) {
                        return resultado;
                    }
                    resultado = a.getApellido2().compareTo(b.getApellido2());
                    if (resultado != 0 ) {
                        return resultado;
                    } else {
                        return a.getNombre().compareTo(b.getNombre());
                   }
                }
            });

También puedes hacer que la clase alumno implemente la interfaz Comparable e implementar eso en el compareTo, de tal forma no hace falta pasarle un comparador y con llamar al método sort con la lista te valdrá. Esto tiene ventajas e inconvenientes vaya.

Collections.sort(lista)
1 respuesta
0nLy

#3 Gracias, ya corregido con la profesora me ha quedado aún más corto, algo tal que así:

Collections.sort(arrayAlumno, new Comparator<Alumno>() {
            @Override
            public int compare(Alumno a, Alumno b) {
                int resultado = (a.getApellido1()+" "+a.getApellido2()+" "+a.getNombre()).compareTo(b.getApellido1()+" "+b.getApellido2()+" "+b.getNombre());
                return resultado;
            }
        });
1 respuesta
Tig

#4 Eso es bastante terrible en cuanto a legibilidad y mantenimiento, si ves ese código dentro de 6 meses te va a costar comprender lo que hace.

Es mejor separar en variables temporales cuyo nombre defina su uso. Y yendo más allá, delega la lógica de construir el nombre completo en Alumno, el Comparator no tiene que conocer detalles de implementación del alumno.

a.getFullname().compareTo(b.getFullname())

No sé si aún se enseña lo de "mejor pocas líneas de código", pero es mejor dejar que los compiladores hagan sus optimizaciones, y nosotros centrarnos en que las cosas funcionen y sean mantenibles.

1 1 respuesta
0nLy

#5 Lo tendré en cuenta! como ya digo llevo 4 meses dando Java en 1º de DAM y todavía estoy pillando todos los conceptos. Aún así muchas gracias a todos :wink:

Usuarios habituales

  • 0nLy
  • Tig
  • MTX_Anubis