Ordenar un ArrayList en Java
El proyecto de este post lo puedes descargar pulsando AQUI.
Una de las funcionalidades más interesantes a la hora de trabajar con estructuras de datos tipo «pila», «cola», «lista» etc. es su ordenación. En el post de «Ordenar Arrays en Java (Con sus indices)» implementamos un API que nos permitía ordenar Arrays y sus indices, que es una funcionalidad muy importante que no ha sido implementada por ningún API conocida y de forma sencilla.
En este post vamos a mostrar como ordenar ArrayList, bien sea con un ArrayList de datos atómicos o con un ArrayList de objetos.
Para realizar estas operaciones necesitaremos trabajar con la Clase «Collections» de Java. No vamos a explicar las características de esta clase, sino que simplemente vamos a utilizarla para ordenar ArrayList’s. Como suele ser habitual en esta web, pasamos a mostrar esta funcionalidad con un ejemplo:
Vamos a tener un ArrayList llamado «arrayListInt» que es un array de enteros y que le pondremos los siguientes valores (sino sabéis el método add, mirar el post «ArrayList en Java, con ejemplos«):
private static ArrayList arrayListInt = new ArrayList<>(); // Guardo datos en el ArrayList arrayListInt.add(3); arrayListInt.add(4); arrayListInt.add(2); arrayListInt.add(6); arrayListInt.add(5); arrayListInt.add(1); arrayListInt.add(7);
Si imprimimos este ArrayList en el orden en el que hemos guardado los elementos, tendremos que el primer elemento sera el numeró ‘3’, el segundo el número ‘6’ y si seguimos el orden, el último será el número ‘7’.
Para ordenar este ArrayList de menor a mayor, vamos a utilizar el método «sort» de la clase Collections:
Collections.sort(arrayListInt);
Con este método nos devolverá el ArrayList ordenado de menor a mayor, siendo la salida la siguiente (en el proyecto que os podéis descargar, podéis ver los método que imprimen por pantalla los ArrayList):
Posicion(1) = 1 Posicion(2) = 2 Posicion(3) = 3 Posicion(4) = 4 Posicion(5) = 5 Posicion(6) = 6 Posicion(7) = 7
Para ordenarlo de mayor a menor, tenemos que crearnos un objeto de la clase Comparator para que compare los elementos y los ponga en orden inverso. Esto lo hacemos de la siguiente manera:
Comparator<Integer> comparador = Collections.reverseOrder(); Collections.sort(arrayListInt, comparador);
Ejecutando esta parte del programa e imprimiendo por pantalla el ArrayList resultante, tenemos el ArrayList ordenado de mayor a menor:
Posicion(1) = 7 Posicion(2) = 6 Posicion(3) = 5 Posicion(4) = 4 Posicion(5) = 3 Posicion(6) = 2 Posicion(7) = 1
Pero ¿Que pasa si lo que tenemos es un ArrayList de objetos de una determinada clase y lo que queremos ordenar ese ArrayList por el valor de un determinado atributo?. Bueno pues hay una sencilla solución que vamos a mostrar a continuación y que consiste en sobreescribir un método de la clase Comparator.
Supongamos que tenemos una clase «Persona» de la siguiente forma:
class Persona { private String nombre; private int edad; public Persona() { } public Persona(String nombre, int edad) { this.nombre = nombre; this.edad = edad; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public int getEdad() { return edad; } public void setEdad(int edad) { this.edad = edad; } @Override public String toString() { return this.getNombre() + " - " + this.getEdad(); } }
Supongamos que tenemos un ArrayList llamado «personas» con los siguientes objetos de la clase persona:
private static ArrayList personas = new ArrayList<>(); ................ ................ personas.add(new Persona("Pepe", 28)); personas.add(new Persona("Juan", 32)); personas.add(new Persona("Paco", 40)); personas.add(new Persona("Susi", 24)); personas.add(new Persona("Lola", 20)); personas.add(new Persona("Jose", 28)); personas.add(new Persona("Dani", 24)); personas.add(new Persona("Sara", 36));
Este ArrayList lo queremos ordenar (de menor a mayor edad) en función de la edad de las personas, por tanto tenemos que sobre escribir el método «compare» de la clase Comparator y llamar al método «sort» de la clase collections. Esto lo hacemos de la siguiente forma:
Collections.sort(personas, new Comparator<Persona>() { @Override public int compare(Persona p1, Persona p2) { return new Integer(p1.getEdad()).compareTo(new Integer(p2.getEdad())); } });
Como vemos lo que hace el método «compare» es comparar dos edades dadas. En este caso estamos comparando dos atributos de tipo «Integer«. Si lo queremos hacer con un String, Double, etc. solo tenemos que cambiar el tipo de dato. Como salida a este código tenemos lo siguiente:
Posicion(1) = Lola - 20 Posicion(2) = Dani - 24 Posicion(3) = Susi - 24 Posicion(4) = Pepe - 28 Posicion(5) = Jose - 28 Posicion(6) = Juan - 32 Posicion(7) = Sara - 36 Posicion(8) = Paco - 40
Si ahora queremos ordenarlo de mayor a menor edad, solo tenemos que cambiar el método «compare» poniendo la comparación al revés:
Collections.sort(personas, new Comparator<Persona>() { @Override public int compare(Persona p1, Persona p2) { // Aqui esta el truco, ahora comparamos p2 con p1 y no al reves como antes return new Integer(p2.getEdad()).compareTo(new Integer(p1.getEdad())); } });
Como resultado de esta ordenación obtenemos lo siguiente:
Posicion(1) = Paco - 40 Posicion(2) = Sara - 36 Posicion(3) = Juan - 32 Posicion(4) = Pepe - 28 Posicion(5) = Jose - 28 Posicion(6) = Dani - 24 Posicion(7) = Susi - 24 Posicion(8) = Lola - 20
Esto es en resumen todo lo necesario para ordenar ArrayList, bien sean por un atributo de una serie de objetos o con datos atómicos (en realidad son objetos que representan datos atómicos, Integer, Double, etc.). No hemos entrado en detalle de explicar las clases Comparator y Collections ya que en principio la finalidad de este post es la de dar una solución a la ordenación de ArrayList.
me salvaste la cola, saludos de uruguay
Muchas gracias!!!
No se difinen la implementación de la interfaz correspondiente para que una clase pueda implementar el metodo
heredado de interfaz. Mucho más efectivo , general y usando los mecanismo POO
Buen tutorial pero tengo un inconveniente en el @Override me salen en los parametros la palabra Object y no me deja cambiarlo por el de la clase que se llama Almacenamiento
Collections.sort(datos, new Comparator() {
@Override
public int compare(Object t, Object t1) {
return new Integer(t.getEdad()).compareTo(new Integer(t1.getEdad()));
}
});
Muy útil ! muchas gracias !
excelente… muchas gracias. !!!!
Por cierto felicidadez muy bien explicado y muy interesante, salu2
Hola paraordenar de mayor a menor no hace falta el comparatorse puede hacer mas facil
//se ordenan
Collections.sort(numeros);
// se invierte el orden
Collections.reverse(numeros);
//y listo solo imprimimos en pantalla
system.out.println("Numeros de mayor a menor"+numeros.toString);
Muchas graciass!!!
Buenas, quizá vengo tarde pero hay un pequeño error en el código donde haces los comparator. Tendría que ser así
Collections.sort(personas, new Comparator<Personas>(){
//El metodo compare
});
Ya que si el Comparator se pone como está publicado, los parametros del metodo compare seran del tipo Object y no del tipo Persona
gracias bro, no sabia porque me tiraba el error cuando ya habia implementado el metodo "compare"
Heyyyyy thank you so much bro.
Regards from Colombia.
Gracias!!! acabas de Salvar el semestre de 20 personas T-T
gracias al igual que al resto al especificar la clase en Compare se fueron los errores.
Buenas Javier.
En efecto, faltaba en el artículo la clase Persona en el Compare en el código del artículo, ya está corregido 🙂
De cualquier manera, estaba correcto en el código completo del repositorio: https://github.com/jarroba/SortArrayList/blob/master/src/SortMain/SortArrayList.java
hola soy nuevo en esto de programar me gustaria saber como aria esta pregunta en la codificacion ¿Se requiere que los valores de las edades y los nombres de las personas sean introducidos por el usuario? gracias
Pues depende de lo que se necesite. Puedes optar por consola o por interfaz de usuario, luego para guardar los datos hay un sin fin de maneras de tratarlos: Arrays, Objetos, List, Maps.
si la explicacion esta muy bien, pero sin utilizar ArrayList y mucho menos String y lo realizo con objetos, como lo puedo ordenar los datos insertado….??????????????
Para poder ordenar algo tiene que estar en alguna estructura como array o List, sino son objetos sin relacción ninguna. Para relacionar objetos del List como indicamos más arriba puedes utilizar compare()
Ramón buenos dias,
Tengo una duda respecto a terminos en Java, cuando dices "Sobreescribir el Metodo" te refieres a ir hasta la clase Compare.java y meterle esas lineas de codigo (basado en los objetos que estoy usando)…
De antemano muchas gracias!…
No ha sido la primera vez que me has salvado, pero en esta me he quedado atorado. (:
No, en este caso no me refiero a sobrescribir métodos. Me he expresado mal, quería decir sustituir un valor por otro con put: nombreMap.put(K clave, V valor);
oh listo! bueno me tocara googlear lo del put: y el map haha (:
Tienes como funciona HashMap en http://jarroba.com/map-en-java-con-ejemplos/ 😉
hola tengo un array list cuyo codigo es el siguiente
public class New {
public static int frec;
public static void main(String[] args) throws IOException {
ArrayList<Person> peoplelist=new ArrayList<Person>();
javax.swing.JFileChooser j= new javax.swing.JFileChooser();
j.showOpenDialog(j);
File f;
String path= j.getSelectedFile().getAbsolutePath();
String lectura="";
f = new File(path);
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String line=null;
String aux;
while((line=br.readLine())!=null){
String [] peopleInfo=line.split(",");
String fecha=peopleInfo[0];
String serie=peopleInfo[1];
String lote=peopleInfo[2].trim();
String frecuencia=peopleInfo[3].trim();
String diferencia=peopleInfo[4].trim();
String Q=peopleInfo[5].trim() ;
String nom_operador=peopleInfo[6];
String num_operador=peopleInfo[7];
frec=Integer.parseInt(frecuencia);
double q=Double.parseDouble(Q);
peoplelist.add(new Person(fecha,serie,lote,frecuencia,diferencia,Q,nom_operador,num_operador));
}
}
}
se trata de obtener el numero mayor en el campo frecuencia e imprimirlo como podria hacerlo? de antemano gracias
Eres un grande, muy bien explicado tío
Que chilera la forma en como lo explican, me ha ayudado a comprender mucho, pero tengo otra duda con esto especificamente:
tengo una clase donde se guardan todas mi ArrayList ejemplo:
ArrayList<Persona>c_persona=new ArrayList<Persona>();
y tengo mi clase persona:
String nombre:
String Apellido:
int Edad.
tengo mi Jframe e otra clase distinta donde introduzco los datos que necesito, toda la parte de ingreso de datos ya lo tengo pero cecesito hacer un ordenamiento con su atributo por edad y mostrarlo, e leído como lo tienen pero no logro comprender: pordrían ayudarme. Gracias desde ya
Gracias por aportar tus conocimientos, saludos..
Hola, tengo un ArrayList de características fisiologicas como presión arterial y glucosa en sangre, se supone que cada una de estas mediciones van asociadas a una fecha. Quería saber como devolver una lista en las que estas características estén ordenadas por fecha. Gracias:)
Hola,
Si tienes un ArrayList con objetos con las características fisiológicas, junto otros datos como fechas, etc. Lo único que tienes que hacer es un sort con un nuevo Comparator() que compare por la variable de fecha.
Buenas tarde tengo que realizar una venta de un libro y me quede trabado en la impresión de la lista del libro me podrian dar una mano? desde ya muchas gracias!
package Main;
import Clientes.Cliente;
import Gestores.GestorVentaDeLibro;
import Comprar.VentaDeLibro;
import Gestores.GestorClienteComun;
import Gestores.GestorClienteVip;
import Gestores.GestorLibrosDigitales;
import Gestores.GestorLibrosImpresos;
import Libros.LibrosDigitales;
import Libros.LibrosImpresos;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.html.HTMLDocument.Iterator;
import Libros.Libro;
public class VenderLibros {
public static void main(String[] args) {
// CREAR UN CLIENTE COMUN
GestorClienteComun gcc = new GestorClienteComun();
Cliente clienteComun = gcc.registrarClienteComun(«Jesus», «Davila», «Aconcagua», 239, «CABA», «CABA»,49877458, «DODO», 32230461, «Jebuss», 500);
//CREAR UN CLIENTE VIP
GestorClienteVip gcv = new GestorClienteVip();
Cliente clienteVip = gcv.registrarClienteVip(«Hugo», «Ferrand», «Pringles», 4239, «Lanus», «BSAS», 1145254781, «Kratos», 26230461, «ZaZaZa», 200);
//CREAR 1 LIBRO DIGITAL
GestorLibrosDigitales ld = new GestorLibrosDigitales();
LibrosDigitales libroDigital = ld.registarLibroDigital(«Expreso de media noche»,»Billy Hayes»,120.50, «kjjkgkjg»,»Aconcagua»,2);
//CREAR UN LIBRO IMPRESO
GestorLibrosImpresos li = new GestorLibrosImpresos();
LibrosImpresos libroImpreso = li.registarLibroImpreso(«Cianuro espumoso»,»Agatha Christie»,180.90, «juerr3″,»Molino»,165);
// VEDER UN LIBRO A UN CLIENTE
GestorVentaDeLibro cc = new GestorVentaDeLibro();
List libros = new ArrayList();
libros.add(libroDigital);
libros.add(libroImpreso);
//Esta es la parte que no entiendo como hacerlo!!!
VentaDeLibro cld = cc.venderLibro(«15/Nov/2014», 1, libros, clienteComun);
System.out.println(«La fecha es: » );
System.out.println(«Libro» + libros.size()+libroImpreso);
System.out.println(«Libro » + libros.size());
// VENDER OTRO LIBRO A OTRO CLIENTE
}
}
Hola Hugo,
Por lo que leo lo que haces tan solo es añadir los libros a un ArrayList, por lo que entiendo que actuaría como de «carro de la compra». Si esto es así (es lo que he entendido), el GestorVentaDeLibro será quien se encargue de hacer el resto y le tendrías que pasar los parámetros en el método venderLibro() (esto es un foreach al ArrayList libros), y así por cada cliente. No sé si es lo que necesitas.
una pregunta, tengo un arraylist de planes turisticos, en donde tengo en cada posicion muchos datos como destino, cupos, costo, fecha, lo que necesito es ordenar cada posicion del array solo con costo para que se me organicen los planes turisticos del que tiene un mayor costo a un menor costo para que un cliente pueda verlos, ahi como se realizaria.
Gracias por adelantado 😀
Hola Sebastián,
lo tienes muy sencillo. Supongo que tendrás una estructura de datos del tipo:
List miLista = ArrayList<PlanTuristico>();
y en cada objeto de cada PlanTuristico tienes los datos que indicas.
Tan solo tienes que hacer sort() con un nuevo Comparator(), al igual que en este ejemplo, donde compares cada precio. Y lo tienes hecho 🙂
una pregunta como hago para ordenar una lista de forma alfabética me explico mi lista es de articulo
mi clases es la siguiente
class xxx{
String autor;
String titulo;
String fecha;
}
y me pide que lo ordene alfabéticamente por el titulo
Hola Jesús,
desde el sort con el compare podrías ir preguntando cuál es mayor que el otro. Un ejemplo sería:
Collections.sort(lista, new Comparator() {
@Override
public int compare(final xxx obj1, final xxx obj2) {
return obj1.getTitulo().compareTo(obj2.getTitulo());
}
} );
es necesario ponerle el «final»,,?
asi estaria bien??…
Collections.sort(lpf, new Comparator() {
@Override
public int compare(PersonaForm o1, PersonaForm o2) {
return o1.getPaterno().compareTo(o2.getPaterno());
}
});
Hola Vitmar,
Estaría correcto también.
Te aclaro lo del final en el parámetro de la función; para que veas que no te influye. No sé si sabes el uso de «final» en variables globales, pero funciona igual en parámetros de función. El «final» convierte a una variable en NO modificable, por ejemplo para constantes (el valor del número pi no lo vamos a querer modificar). Al aplicarlo al parámetro de una función estamos diciendo que no vamos a modificar el dato que nos entre a la función. ¿Podríamos no ponerlo? Podríamos, pero al poner «final» a una variable el ordenador consume menos recursos (por tanto menos batería si nuestro programa se ejecuta en un móvil por ejemplo)
Gracias…
Gracias me sirvio mucho asi “Collections.sort(personas, new Comparator()”…
Hola muchas gracias por el tutorial de verdad me ayudo mucho, si me pudieras ayudar con este punto te lo agradeceria aun mas.
tengo un arraylist que esta cargado con informacion de libro, es decir cada posicion en el arraylist tiene los siguientes datos: (int CodigodelLibro, String Titulo, String Autor, String Editorial)
y necesito que ingresando un autor el programa recorra el arraylist e imprima los libros que sean del mismo autor.
muchas gracias por adelantado
Hola Simon,
entiendo que tienes un ArrayList de objetos Libro. Si fueran objetos simples te diría que utilizaras contains(), pero como son objetos complejos tendrás que recorrerlos con un foreach e ir buscando uno a uno (mira en http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html)
Buenas, estoy creando una clase para ordenar una lista de objetos según su atributo
El objeto de la lista se llama cliente.
Hago el método para ordenar por nombre y sobrescribo, pero me salen 3 errores:
-Me sugiere que declare la clase abstracta
-Me dice que el método sort no es aplicable para esos argumentos
-Me dice el método compare debería sobrescribir o implementar un método «supertype»
Adjunto el código y agradezco la ayuda.
import java.util.Collections;
import java.util.Comparator;
public class Ordenar implements Comparable {
public Cliente[] tempClientes;
public Articulo[] tempArticulos;
public Ordenar(Cliente[] clientes, Articulo[] articulos){
tempClientes = clientes;
tempArticulos = articulos;
}
public Cliente[] sortNombre(Cliente[] lista){
tempClientes = lista;
Collections.sort(tempClientes, new Comparator(){
@Override
public int compare(Cliente p1, Cliente p2){
return new String(p1.getNombre()).compareTo(new String(p2.getNombre()));
}
});
return tempClientes;
}
}
Debo agradecerte bastante por este tutorial, me ha servido muchisimo, adelante con tu labor.
Hola
Muchas gracias por la explicación, me ha servido bastante.
Tengo una duda. Estoy haciendo un proyecto en NetBeans e hice una clase en la cual sobre escribí el compare de la clase Comparator como lo mencionas.
NetBeans me dice que mi clase no es abstracta y que no sobre escribo el método compare en Comparator.
¿Qué está sucediendo?
Hola,
fíjate que el «new Comparator(){…}» lo estés pasando como evento (como parámetro de la función sort() ). Y dentro del cuerpo de «Comparator(){aquí entre las llaves}» sea donde hagas la sobrescritura (@override) del método compare(). Si lo pones fuera te dirá lo de que tu clase no es abstracta 😉
nesesito un ejemplo de optener valores numericos de un joptionpane solo uno… y este que almacene todos los valores numericos en un array ya k ya llevo hecho hasta los operandos solo me falta almacenar los valores numericos para k asi me haga la operacion como si fuera una calculadora
Hola bek,
no es el tema del artículo, pero en la página oficial de Java tienes un ejemplo de JOptionPane (ver en http://docs.oracle.com/javase/7/docs/api/javax/swing/JOptionPane.html). El resto es utilizar los valores como te comentamos 😉
Excelente solución, ahora, me queda una duda, ¿como puedo lograr eso mismo pero alfabéticamente?
Tengo que ordenar por unidadEjecutora y por entidad varios elementos
unidadejecutora|entidad
128 Guanajuato
128 Aguascalientes
101 Aguascalientes
101 DistritoFederal
tendría que quedar así.
unidadejecutora|entidad
101 Aguascalientes
101 DistritoFederal
128 Aguascalientes
128 Guanajuato
apreciaría tu ayuda. gracias!
Hola Ramón,
se hace igual, con el método sort(), ya que ordena también listas de Strings. Para tu ejemplo: miLista = new ArrayList ();
List
miLista.add(«128 Guanajuato»);
miLista.add(«128 Aguascalientes»);
miLista.add(«101 Aguascalientes»);
miLista.add(«101 DistritoFederal»);
Collections.sort(miLista);
Devuelve el resultado ordenado de:
101 Aguascalientes
101 DistritoFederal
128 Aguascalientes
128 Guanajuato
Te respondo otra vez, ya que creo que te refieres a que tienes los datos en objetos Pojo (y dejo el anterior comentario, por si te sirviera). Es decir, que tendrías una clase que voy a llamar «Entidad.java» en la que guardas un número entero y un nombre. Por lo que podemos rellenar la lista del siguiente modo:
List miLista = new ArrayList ();
miLista.add(new Entidad(128, «Guanajuato»));
miLista.add(new Entidad(128, «Aguascalientes»));
miLista.add(new Entidad(101, «Aguascalientes»));
miLista.add(new Entidad(101, «DistritoFederal»));
Luego, para ordenar, solo has de seguir el tutorial y verás que puedes sobrescribir Comparator como sigue:
Collections.sort(miLista, new Comparator() {
@Override
public int compare(Entidad ent1, Entidad ent2) {
return new Integer(ent1.id).compareTo(ent2.id);
}
});
La anterior devuelve lo que necesitas, ya que ordena por id. Si quisieras ordenar además por nombre, tendrías que jugar con los enteros devueltos por el método compareTo(). Aunque te recomendaría que implementaras la clase Comparable dentro de la clase Pojo y que comparases uno a uno como el id del ejemplo anterior (y lo mismo para el String del nombre): compararId = new Comparator () {
public static Comparator
public int compare(Entidad ent1, Entidad ent2) {
return Integer(ent1.id).compareTo(ent2.id);
}
};
Te agradezco la ayuda tocayo. Lo checo y te comento en breve!
Apliqué lo siguiente…
Tengo mi lista..
unidadejecutora|entidad
128 Guanajuato
128 Aguascalientes
101 Aguascalientes
101 DistritoFederal
//implementé comparable como me dijiste en mi clase Pojo
public class EstructuraReporte implements Comparable {
private Integer unidad_ejecutora;
private String entidad;
public Integer getUnidad_ejecutora() {
return unidad_ejecutora;
}
public void setUnidad_ejecutora(Integer unidad_ejecutora) {
this.unidad_ejecutora = unidad_ejecutora;
}
public String getEntidad() {
return entidad;
}
public void setEntidad(String entidad) {
this.entidad = entidad;
}
//aplique el compareTo
public int compareTo(EstructuraReporte o) {
//concatenando el valor texto de unidad_ejecutora y la entidad
String a=new String(String.valueOf(this.unidad_ejecutora)+this.entidad);
String b=new String(String.valueOf(o.unidad_ejecutora)+o.entidad);
//comparo y listo.
return a.compareTo(b);
}
}
y con un respectivo
Collections.sort(lista);
obtuve la lista con el orden que quería
unidadejecutora|entidad
101 Aguascalientes
101 DistritoFederal
128 Aguascalientes
128 Guanajuato
Agradezco la orientación…
Estupendo Ramón, ahora a seguir adelante 😀
interesante