25 abril 2009

Filtro de objetos con un atributo repetido

Escenario
Se retorna una colección de objetos proveniente de los WebServices y se requiere filtrar, la colección, de forma tal que solo la primera ocurrencia de cada valor atributo repetido quede dentro de la colección. Eliminar los demás duplicados.

Solución 1 - No muy buena
Al principio yo planteé controlar la duplicidad de objetos a través de un flag y una segunda colección de objetos a la cual enviar los objetos. A continuación les pongo mi solución:
List tempCommActions = dataAccessService.getCommercialActions(userLoginId, cic);
List commercialActions = null;
        if (tempCommActions != null)
        {
            commercialActions = new ArrayList();
            boolean flag = true;
            for (int i = 0; i < tempCommActions.size(); i++)
            {
                CommercialAction bean1 = (CommercialAction) tempCommActions.get(i);
                for (int j = 0; j < commercialActions.size(); j++)
                {
                    CommercialAction bean2 = (CommercialAction) commercialActions.get(j);
                    if (bean1.getCampaignCode().equals(bean2.getCampaignCode()))
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)
                {
                    commercialActions.add(bean1);
                }
            }
        }

Esta solución no termina siendo muy eficiente por la cantidad de objetos que se manejan, además de las reiteradas iteraciones a las listas.

Solución 2 - Mejor
Pero, consultando con uno de mis compañeros... encontramos una mejor manera de implementar esta solución. Para la cual empleamos un iterator para recorrer la lista y un objeto de tipo Set que nos serviría para ir guardando el atributo que comparamos.
        List commercialActions = dataAccessService.getCommercialActions(userLoginId, cic);

        Set visitedCampaignCodes = new HashSet();        
        for (Iterator iterator = commercialActions.iterator(); iterator.hasNext();)
        {
            CommercialAction commercialAction = (CommercialAction) iterator.next();
            if (visitedCampaignCodes.contains(commercialAction.getCampaignCode()))
            {
                iterator.remove();
            }
            else
            {
                visitedCampaignCodes.add(commercialAction.getCampaignCode());
            }
        } 

Genial no? Y eso que mi compañero agregó... "es posible que haya una mejor solución aun". :P

2 comentarios:

Unknown dijo...

Estás con JDK 5? mejoralo con Generics y Enhanced for loop

Armando dijo...

Trabajamos aun con 1.4 mi estimado Lennon.