A ideia é muito simples cria-se uma interface chamada Filter<T> que é um contrato, que relata como deve ser o objeto que queremos encontrar, e então cria-se rotinas simples baseando neste contrato (a interface) para buscas.
interface Filter<T>
- /**
- * Filtro de objeto, que testa se um obejto candidato T confere com o filtro.
- * @author Tomaz Lavieri
- * @param <T> o tipo de objetos que o filtro testa.
- * @see CollectionUtils
- */
- public interface Filter<T> {
- /**
- * Verifica se o objeto candidato passa pelo filtro.
- * @param candidate Objeto candidato.
- * @return <tt>true</tt> - caso o candidato passe no filtro.
- * <br><tt>false</tt> - caso o candidato não pesse pelo filtro.
- */
- public boolean match(T candidate);
- }
É com essa ideia do filtro, que se cria um critério para buscas em coleções, por exemplos, vamo supor que agente tem uma classe chamada Pessoa e que queremos buscar todas as pessoas que contenham o nome "João" e que a idade seja maior ou igual a 18 anos.
- Filter<Pessoa> joaoMaioresDe18 = new Filter<Pessoa>() {
- public boolean match(Pessoa candidate) {
- boolean nomeOk = candidate.getNome() != null ?
- candidate.getNome().toLowerCase().contains("joão") :
- false;
- return nomeOk && candidate.getIdade() >= 18;
- }
- };
Agora temos um critério de busca que foi guardado na variável joaoMaioresDe18 e podemos checar facilmente se qualquer pessoa passa pelo criterio utilizando joaoMaioresDe18.match(pessoa); este retorna true caso a pessoa seja um joão maior de 18 anos.
Agora podemos criar uma rotina para buscar em uma lista, todas as pessoas que pertençam ao criterio informado, ficando assim:
- List<Pessoa> pessoas = getAllPessoas(); //abstraindo como essa lista é obtida.
- List<Pessoa> resultado = new ArrayList<Pessoa>(0); //guarda o resultado
- for (Pessoa pessoa : pessoas) //realizando a busca
- if (joaoMaioresDe18.match(pessoa))
- resultado.add(pessoa);
Após isto, temos em resultado, todas as pessoas que contém o nome "joão" e que são maiores de idade.
Ficou bom, mais o processo pode ser automatizado e tornar-se ainda melhor, para isso é criado uma classe utilitária chamada CollectionUtils onde podemos guardar rotinas como:
- Buscar todos os resultados que coincidem com o filtro - findAllMatch
- Buscar todos os resultados que não coincidem com o filtro - findAllNotMatch
- Buscar o primeiro resultado que coincidir com o filtro - findFirstMatch
- Buscar o primeiro resultado que não coincir com o filtro - findFirstNotMatch
- Reter na lista total apenas os objetos que coincidirem com o filtro - retainAll
- Remover da lista total todos os objetos que coincidirem com o filtro - removeAll
- Adciona a uma segunda lista todos os itens da primeira lista que coincidirem com o filtro - addAllMatch
- Adciona a uma segunda lista todos os itens da primeira lista que não coincidirem com o filtro - addAllNotMatch
Colocarei aqui apenas um trecho de CollectionUtils e o link para o código completo segue aqui http://pastebin.com/f9d80cb7
class CollectionUtils
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- import java.util.List;
- /**
- * Classe utilitária para manipular coleções
- * @author Tomaz Lavieri
- */
- public class CollectionUtils {
- /**
- * Não é possivel instaciar CollectionUtils.
- */
- private CollectionUtils(){}
- /**
- * Busca todos os objetos <b>T</b> na lista de <tt>candidates</tt> que
- * conferem com o <tt>filter</tt>.
- * <BR>
- * <BR>Tem o resultado inverso a {@link #findAllNotMatch(Collection, Filter)}
- * @param <T> o tipo de objeto a ser buscado.
- * @param candidates a coleção de condidatos aonde deseja-se realizar a
- * busca.
- * @param filter o filtro que será usado para <b><u>aceitar</u></b> um
- * candidato no resultado da busca.
- * @return todos os itens que passaram pelo filtro.
- * @see #findAllNotMatch(Collection, Filter)
- */
- public static <T> List<T> findAllMatch(Collection<? extends T> candidates,
- Filter<T> filter) {
- List<T> matchs = new ArrayList<T>(0);
- addAllMatch(candidates, filter, matchs);
- return matchs;
- }
- /**
- * Adciona a coleção <tt>recipient</tt> todos os objetos <tt>T</tt> da lista
- * de <tt>candidates</tt> que coincidirem com o <tt>filter</tt>.
- * <BR>
- * <BR>Adciona o inverso dos itens de <tt>candidates</tt> que
- * {@link #addAllNotMatch(Collection, Filter, Collection)} adcionaria.
- * @param <T> o tipo de objeto a ser adcionado.
- * @param candidates a coleção de candidatos a serem adcionados ao
- * <tt>recipient</tt>.
- * @param filter o filtro que será usado para <b><u>aceitar</u></b> um
- * candidato a ser adcionado ao <tt>recipient</tt>.
- * @param recipient coleção onde os objetos serão adicionados.
- * @see #addAllNotMatch(Collection, Filter, Collection)
- */
- public static <T> void addAllMatch(Collection<? extends T> candidates,
- for (T object : candidates)
- if (filter.match(object))
- recipient.add(object);
- }
- //... restante da classe segue no link indicado
- }
Agora com essas duas classes, basta criar um filtro, e mandar junto com a coleção, para CollectionUtils e receber os resultados.
Desta forma espera-se aumentar a produtividade, e facilitar a manipulação de coleções.
Filter.java
CollectionUtils.java
Nenhum comentário:
Postar um comentário