API para TREE

7 respostas
phlopes

Olá Pessoal, no meu banco de dados tenho categorias que tem um atributo parent que é outra categoria. Elas podem ter N níveis.

Gostaria de listar todos os níveis começando pelos pais, pode ex:

Eletrodomésticos -> Cozinha
Eletrodomésticos -> Cozinha -> Microondas
Eletrodomésticos -> Cozinha -> Microondas - > Brastemp
Eletrodomésticos -> Cozinha -> Microondas - > Philips
Banho -> Toalhas
Banho -> Toalhas -> Algodão

Ps: Eu vou listando todos os itens , mas levando todos os níveis anteriores também.

A pergunta é: Existe alguma API que trabalha melhor com isso?? Alguma dica que eu possa usar para desenvolver?

Aceito sugestões.

Obrigado !

7 Respostas

maschiojv

A unica coisa que posso dizer pra te ajudar é que com o pattern Visitor o teu código vai ficar bem mais simples e organizado.

gomesrod

Se fosse cada pai referenciando os filhos seria fácil, basta uma busca em largura simples…
Mas pelo que você disse o filho é que referencia o pai?

phlopes

Isso, na verdade cada filho tem o id do pai, o pai no nível maior não tem id nenhum.

gomesrod

É, isso complica bastante… :frowning:

Na API não tem nada pronto para tratar esse tipo de estrutura, pensei em duas soluções que possam servir ao seu caso mas cada uma tem um pequeno “probleminha”

  1. Varrer todos esses registros e organiza-los em uma estrutura tipo árvore em que cada pai tem uma collection de filhos. Fazer o que você precisa nesse tipo de estrutura ficaria mais simples (só corrigindo, ao contrário do que eu disse antes, a busca em largura não iria funcionar, me enganei :oops:).
    Problema: A performance seria completamente horrível.

  2. Fazer um sort nesses registros, implementando algum esquema de comparação que leve em conta os pais para fazer com que o resultado saia da maneira desejada.
    Problema: Não tive como pensar a fundo nessa solução, não tenho 100% de certeza que é possível de implementar.

Devem existir soluções melhores, vamos esperar um pouco e ver se aparece mais alguém para ajudar. Tem uns experts em algoritmo aqui no fórum, quem sabe dão uma passadinha.
Se não rolar novas idéias e você quiser tentar uma dessas soluções aí podemos detalhar mais.

maschiojv

Como eu disse, usando o pattern Visitor fica bem simples, se bem que aqui eh um visitor meio falcatrua:

public class Main {

	public static void main(String[] args) {

		//todas as categiorias, como venho do banco
		Collection<Categoria> todas = new ArrayList<Categoria>();

		Categoria ele = new Categoria("Eletrodomésticos");
		todas.add(ele);
		Categoria coz = new Categoria("Cozinha", ele);
		todas.add(coz);
		Categoria mic = new Categoria("Microondas", coz);
		todas.add(mic);
		Categoria bra = new Categoria("Brastemp", mic);
		todas.add(bra);
		Categoria phi = new Categoria("Philips ", mic);
		todas.add(phi);
		Categoria ban = new Categoria("Banho");
		todas.add(ban);
		Categoria toa = new Categoria("Toalhas", ban);
		todas.add(toa);
		Categoria alg = new Categoria("Algodão", toa);
		todas.add(alg);

		for (Categoria categoria : todas) {

			if(categoria.getParent() != null) {

				StringBuilder sb = new StringBuilder();
				categoria.print(sb);

				System.out.println(sb);
			}
		}
	}
}
public class Categoria {

	private String nome;
	private Categoria parent;

	public Categoria(String nome) {
		this(nome, null);
	}

	public Categoria(String nome, Categoria parent) {
		this.nome = nome;
		this.parent = parent;
	}

	public Categoria getParent() {
		return parent;
	}

	public void print(StringBuilder sb) {

		if(parent != null) {

			parent.print(sb);
			sb.append(" -> ");
		}

		sb.append(nome);
	}
}
gomesrod

Acho que nós estamos pensando em partes diferentes do problema! :slight_smile:

Você mostrou a solução para imprimir cada Categoria, enquanto eu estava preocupado em como ordená-las.

maschiojv
gomesrod:
maschiojv:
...
Acho que nós estamos pensando em partes diferentes do problema! :)

Você mostrou a solução para imprimir cada Categoria, enquanto eu estava preocupado em como ordená-las.

Acho que agora ordenar é só uma evoluçãozinha da idéia, por exemplo:

public class Main {

	public static void main(String[] args) {

		//todas as categiorias, como venho do banco, e um HashSet (desordenado) 
		Collection<Categoria> todas = new HashSet<Categoria>();

		Categoria ele = new Categoria("Eletrodomésticos");
		todas.add(ele);
		Categoria coz = new Categoria("Cozinha", ele);
		todas.add(coz);
		Categoria mic = new Categoria("Microondas", coz);
		todas.add(mic);
		Categoria bra = new Categoria("Brastemp", mic);
		todas.add(bra);
		Categoria phi = new Categoria("Philips ", mic);
		todas.add(phi);
		Categoria ban = new Categoria("Banho");
		todas.add(ban);
		Categoria toa = new Categoria("Toalhas", ban);
		todas.add(toa);
		Categoria alg = new Categoria("Algodão", toa);
		todas.add(alg);

		List<Nivel> niveis = new ArrayList<Nivel>();

		for (Categoria categoria : todas) {

			if(categoria.getParent() != null) {

				Nivel nivel = new Nivel();
				categoria.visit(nivel);

				niveis.add(nivel);
			}
		}

		Collections.sort(niveis);

		for (Nivel nivel : niveis) {
			System.out.println(nivel);
		}
	}
}
public class Categoria {

	private String nome;
	private Categoria parent;

	public Categoria(String nome) {
		this(nome, null);
	}

	public Categoria(String nome, Categoria parent) {
		this.nome = nome;
		this.parent = parent;
	}

	public Categoria getParent() {
		return parent;
	}

	public void visit(Nivel nivel) {

		if(parent != null) {

			parent.visit(nivel);
		}

		nivel.addCaminho(nome);
	}
}
public class Nivel implements Comparable<Nivel> {

	private List<String> caminho = new ArrayList<String>();

	public void addCaminho(String nome) {
		caminho.add(nome);
	}

	public int compareTo(Nivel o) {

		int c = -1;

		int size = caminho.size();
		size = o.caminho.size() > size ? o.caminho.size() : size;

		for (int i = 0; i < size; i++) {

			if(caminho.size() -1 < i) {
				return -1;
			}
			if(o.caminho.size() -1 < i) {
				return 1;
			}

			c = caminho.get(i).compareTo(o.caminho.get(i));

			if(c != 0) {
				return c;
			}
		}

		return c;
	}

	@Override
	public String toString() {

		StringBuilder sb = new StringBuilder();

		for (String str : caminho) {
			sb.append(str).append(" -> ");
		}

		return sb.substring(0, sb.length() -4);
	}
}
Criado 14 de outubro de 2009
Ultima resposta 15 de out. de 2009
Respostas 7
Participantes 3