Recursividade com Java

Oi, estou tentando criar um método de forma recursiva, que me mostre todos os centros de custo filhos, por exemplo:

image

Se o pai for o centro de custo 1, ira me retornar o 3, 4 e 5.

Não tenho pratica nenhum com recursividade, mas vou por abaixo o fonte que tentei até agora.

public class Teste {

    public static List<CentroCusto> centroCustos = new ArrayList<>();
    public static List<CentroCusto> centroCustos2 = new ArrayList<>();

    public static void main(String[] args) {
        build();

        CentroCusto c1 = new CentroCusto();
        c1.setId(1L);
        buscarFilhos(c1);
        System.out.println(centroCustos2);
    }

    private static CentroCusto buscarFilhos(CentroCusto ccu) {
        if (!centroCustos.stream().map(CentroCusto::getCentroCustoPai).filter(Objects::nonNull).anyMatch(centroCusto -> centroCusto.getId().equals(ccu.getId()))) {
            centroCustos2.add(ccu);
            return ccu;
        }
        for (CentroCusto centroCusto : centroCustos) {
            if (Objects.nonNull(centroCusto.getCentroCustoPai()) && centroCusto.getCentroCustoPai().getId().equals(ccu.getId())) {
                return buscarFilhos(centroCusto);
            }
        }
        return null;
    }

    private static void build() {
        CentroCusto c1 = new CentroCusto();
        c1.setId(1L);
        CentroCusto c2 = new CentroCusto();
        c2.setId(2L);
        c2.setCentroCustoPai(c1);
        CentroCusto c3 = new CentroCusto();
        c3.setId(3L);
        c3.setCentroCustoPai(c2);
        CentroCusto c4 = new CentroCusto();
        c4.setId(4L);
        c4.setCentroCustoPai(c2);
        CentroCusto c5 = new CentroCusto();
        c5.setId(5L);
        c5.setCentroCustoPai(c1);
        CentroCusto c6 = new CentroCusto();
        c6.setId(6L);
        CentroCusto c7 = new CentroCusto();
        c7.setId(7L);
        c7.setCentroCustoPai(c6);
        CentroCusto c8 = new CentroCusto();
        c8.setId(8L);
        c8.setCentroCustoPai(c7);
        centroCustos.add(c1);
        centroCustos.add(c2);
        centroCustos.add(c3);
        centroCustos.add(c4);
        centroCustos.add(c5);
        centroCustos.add(c6);
        centroCustos.add(c7);
        centroCustos.add(c8);
    }

}

public class CentroCusto {
    private Long id;
    private CentroCusto centroCustoPai;
    // Gettes e Setters
}

No CentroCusto além de ter uma referência para o pai, mantenha também uma referência para os filhos, veja:

import java.util.LinkedList;
import java.util.List;

public class CentroCusto {

    private Long id;
    private CentroCusto pai;
    private List<CentroCusto> filhos = new LinkedList<>();

    public List<CentroCusto> getFilhos() {
        return filhos;
    }

    public CentroCusto getPai() {
        return pai;
    }

    public Long getId() {
        return id;
    }

    public void setPai(CentroCusto pai) {
        pai.filhos.add(this);
        this.pai = pai;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

Aí fica bem fácil:

import java.util.ArrayList;
import java.util.List;

public class Teste {

    public static List<CentroCusto> centroCustos = new ArrayList<>();

    public static void main(String[] args) {
        build();
        for (CentroCusto cc : centroCustos) {
            imprimir(cc);
        }
    }

    private static void imprimir(CentroCusto cc) {
        imprimirRecursivamente("", cc);
    }

    private static void imprimirRecursivamente(String indent, CentroCusto cc) {
        System.out.println(indent + "Centro de custo " + cc.getId());
        for (CentroCusto filho : cc.getFilhos()) {
            imprimirRecursivamente("    " + indent, filho);
        }
    }

    private static void build() {
        CentroCusto c1 = new CentroCusto();
        c1.setId(1L);
        CentroCusto c2 = new CentroCusto();
        c2.setId(2L);
        c2.setPai(c1);
        CentroCusto c3 = new CentroCusto();
        c3.setId(3L);
        c3.setPai(c2);
        CentroCusto c4 = new CentroCusto();
        c4.setId(4L);
        c4.setPai(c2);
        CentroCusto c5 = new CentroCusto();
        c5.setId(5L);
        c5.setPai(c1);
        CentroCusto c6 = new CentroCusto();
        c6.setId(6L);
        CentroCusto c7 = new CentroCusto();
        c7.setId(7L);
        c7.setPai(c6);
        CentroCusto c8 = new CentroCusto();
        c8.setId(8L);
        c8.setPai(c7);
        centroCustos.add(c1);
        centroCustos.add(c2);
        centroCustos.add(c3);
        centroCustos.add(c4);
        centroCustos.add(c5);
        centroCustos.add(c6);
        centroCustos.add(c7);
        centroCustos.add(c8);
    }
}

Saída do programa:

Centro de custo 1
    Centro de custo 2
        Centro de custo 3
        Centro de custo 4
    Centro de custo 5
Centro de custo 2
    Centro de custo 3
    Centro de custo 4
Centro de custo 3
Centro de custo 4
Centro de custo 5
Centro de custo 6
    Centro de custo 7
        Centro de custo 8
Centro de custo 7
    Centro de custo 8
Centro de custo 8
1 curtida

Obrigado pela solução @staroski ficou top, mas infelizmente eu vou precisar resolver essa questão sem alterar a classe CentroCusto :frowning:

@staroski Eu alterei o seu fonte e acho que consegui, dá uma olhada, acho que tá certo, obrigado :smiley:

public class Teste {

    public static List<CentroCusto> centroCustos = new ArrayList<>();
    public static List<CentroCusto> centroCustos2 = new ArrayList<>();

    public static void main(String[] args) {
        build();
        CentroCusto c1 = centroCustos.get(0);
        imprimirRecursivamente(c1);

        for (CentroCusto centroCusto : centroCustos2) {
            if (isFilho(centroCusto)) {
                System.out.println(centroCusto.getId() + " é filho.");
            }
        }
    }

    private static void imprimirRecursivamente(CentroCusto cc) {
        for (CentroCusto filho : getFilhos(cc)) {
            imprimirRecursivamente(filho);
            centroCustos2.add(filho);
        }
    }

    private static List<CentroCusto> getFilhos(CentroCusto cc) {
        List<CentroCusto> ccus = new ArrayList<>();
        for (CentroCusto centroCusto : centroCustos) {
            if (Objects.nonNull(centroCusto.getCentroCustoPai()) &&
                    centroCusto.getCentroCustoPai().getId().equals(cc.getId())) {
                ccus.add(centroCusto);
            }
        }
        return ccus;
    }

    private static boolean isFilho(CentroCusto ccu) {
        return !centroCustos.stream().map(CentroCusto::getCentroCustoPai).filter(Objects::nonNull).anyMatch(centroCusto -> centroCusto.getId().equals(ccu.getId()));
    }

    private static void build() {
        CentroCusto c1 = new CentroCusto();
        c1.setId(1L);
        CentroCusto c2 = new CentroCusto();
        c2.setId(2L);
        c2.setCentroCustoPai(c1);
        CentroCusto c3 = new CentroCusto();
        c3.setId(3L);
        c3.setCentroCustoPai(c2);
        CentroCusto c4 = new CentroCusto();
        c4.setId(4L);
        c4.setCentroCustoPai(c2);
        CentroCusto c5 = new CentroCusto();
        c5.setId(5L);
        c5.setCentroCustoPai(c1);
        CentroCusto c6 = new CentroCusto();
        c6.setId(6L);
        CentroCusto c7 = new CentroCusto();
        c7.setId(7L);
        c7.setCentroCustoPai(c6);
        CentroCusto c8 = new CentroCusto();
        c8.setId(8L);
        c8.setCentroCustoPai(c7);
        centroCustos.add(c1);
        centroCustos.add(c2);
        centroCustos.add(c3);
        centroCustos.add(c4);
        centroCustos.add(c5);
        centroCustos.add(c6);
        centroCustos.add(c7);
        centroCustos.add(c8);
    }

}