Eliminar Objetos Repetidos De Una Lista [Java]

¡Qué tal curioso!, antes de comenzar a leer mi publicación te invito a que me conozcas. Mi nombre es Jesús Alberto Sánchez Tecalco y desde ahora podrás encontrar en mis contenidos: tips, soluciones a problemas y otros tipos de publicaciones relacionadas a la programación. Actualmente soy usuario Linux por lo que también acostumbro aportar pequeñas ideas para mejorar tu sistema, parar “enchularlo” o para solucionar algún problema. Soy estudiante de la carrera de Ing. en Sistemas Computacionales y mi lenguaje de programación favorito es Java (con él he crecido). Me gusta la música de todo tipo y amo los tacos al pastor.

Ahora, entrando un poco a materia y sin rodeos, vamos a pensar en el siguiente problema: Imagina que tienes una lista de objetos y algunos de ellos se encuentran repetidos. Lo anterior podría causar un gran problema, ya que en tu aplicación tendrías información repetida que ocupa mucho espacio tanto de forma visual (En una tabla, Lista, Combo, etc.), así como en memoria.

A continuación te mostraré una forma de limpiar tu lista de aquellos elementos que tienes repetidos. Para que funcione, tus objetos deben tener como mínimo un atributo que los identifique. Como ejemplo propongo un objeto llamado Persona con los siguientes atributos (olvidé decirte que para el tip usaré Java, pero no dudo que tomando únicamente el algoritmo funcione en otros lenguajes):

Persona

identificador Integer
nombre String
edad Integer

Dejaré esto por aquí:

package tip01;

/**
 *
 * @author Jesús A. Sánchez Tecalco
 *
 */

public class Persona {
 private Integer identificador;
 private String nombre;
 private Integer edad;

 public Persona() {
 }

 public Persona(Integer identificador, String nombre, Integer edad) {
 this.identificador = identificador;
 this.nombre = nombre;
 this.edad = edad;
 }

 public Integer getIdentificador() {
 return identificador;
 }

 public void setIdentificador(Integer identificador) {
 this.identificador = identificador;
 }

 public String getNombre() {
 return nombre;
 }

 public void setNombre(String nombre) {
 this.nombre = nombre;
 }

 public Integer getEdad() {
 return edad;
 }

 public void setEdad(Integer edad) {
 this.edad = edad;
 }

 @Override
 public String toString() {
 return "Persona{" + "identificador=" + identificador + ", nombre=" + nombre + ", edad=" + edad + '}';
 }
}

La clase Persona es una pequeñísima abstracción de una persona, está clase cuenta con 2 constructores y con los respectivos gets y sets de cada atributo. El método toString nos permitirá visualizar como texto los valores que incluyen los objetos de una forma más rápida.

Ahora, el pequeño algoritmo para limpiar la lista:

package tip01;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 *
 * @author Jesús A. Sánchez Tecalco
 *
 */

public class Test {

 static List generarLista() {
 List personas = new ArrayList(10);

 personas.add(new Persona(1, "Juan", 21));
 personas.add(new Persona(2, "Martin", 18));
 personas.add(new Persona(3, "Luis", 26));
 personas.add(new Persona(1, "Juan", 21));
 personas.add(new Persona(6, "Daniela", 22));
 personas.add(new Persona(3, "Luis", 26));
 personas.add(new Persona(6, "Alberto", 20));
 personas.add(new Persona(7, "Araceli", 29));
 personas.add(new Persona(1, "Juan", 21));
 personas.add(new Persona(6, "Daniela", 22));

 return personas;
 }

 public static void main(String[] args) {

 List personas = generarLista();

 System.out.println("Lista original:");
 for(Persona p : personas) {
 System.out.println(p);
 }
 System.out.println("---------------------");

 List listaLimpia = new ArrayList();

 //Forma número 1 (Uso de Maps).
 Map<Integer, Persona> mapPersonas = new HashMap<Integer, Persona>(personas.size());

 //Aquí está la magia
 for(Persona p : personas) {
 mapPersonas.put(p.getIdentificador(), p);
 }

 //Agrego cada elemento del map a una nueva lista y muestro cada elemento.
 System.out.println("Lista sin repetidos:");
 for(Entry<Integer, Persona> p : mapPersonas.entrySet()) {
 listaLimpia.add(p.getValue());
 System.out.println(p.getValue());
 }
 System.out.println("---------------------");
 }
}

Para comenzar debemos tener una lista con objetos repetidos (en el ejemplo anterior tenemos la lista personas), a continuación debemos crear un Map (Un map básicamente es una lista de objetos con un clave y un valor) que contenga como clave el identificador del objeto y como valor el mismo objeto (lo anterior lo logramos iterando sobre la lista y metiendo con el método put el identificador de la persona y como valor el objeto).

Lo sé mi explicación puede ser rara pero… ¿qué crees?, el bendito map hace el trabajo por ti, si una de las claves la encuentra repetida remplazará el objeto existente por el nuevo, por lo que al final deberías tener un mapa con la lista de personas limpia.

Para poder generar una nueva lista con los objetos sin repetir lo que hacemos es crear un Entry (básicamente es una lista clave, objeto), este es un objeto especial que lo retorna el método entrySet() de un map, cuando se itera sobre él tenemos acceso al key y value del elemento del map, por lo que no queda más que agregar a una nueva lista el value de cada valor del Entry.

La salida para el ejemplo anterior es la siguiente: Captura

Para terminar te dejo documentación para que analices el funcionamiento de las interfaces así como sus implementaciones de List, Map y Entry:

Cabe mencionar que esto debe ser usado de forma moderada, el excesivo uso tendrá un caro costo, es importante recordar que existen técnicas que permiten prevenir estos problemas, por mencionar alguna, sí la información es extraída de una base de datos, desde tu consulta puedes eliminar repetidos usando un group by o un distinct (Según el gestor de base de datos que uses).

Comentarios Recientes