Über Objekt, das Objekte desselben Typs enthält iterieren

krgewb

Top Contributor
Ich habe folgende Klasse
Java:
public class GDTO {

    private String id;
    private List<GDTO> g = new ArrayList<>();
    
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
    
    public List<GDTO> getG() {
        return g;
    }

    public void setG(List<GDTO> g) {
        this.g = g;
    }
}

Nun will ich (z.B. rekursiv!?) alle Objekte vom Typ GDTO bekommen, um sie einer ArrayList hinzuzufügen.
 
Da gibt es viele Möglichkeiten. Da wäre schon einmal die Frage: soll das eine Methode der Klasse werden oder willst Du das außerhalb der Klasse haben?
 
Ich habe folgende Klasse
g ist ein furchtbarer Name. nestedGdtos waere vielleicht eine Alternative?

Nun will ich (z.B. rekursiv!?) alle Objekte vom Typ GDTO bekommen, um sie einer ArrayList hinzuzufügen.
Da ist dir Frage: Ist das ein Baum oder ein ungerichteter Graph? Ersteres ist einfach, bei zweiter Variante wirst du ein Set mitfuehren muessen um sicherzugehen dass du nicht ein GDTO erneut (und wieder und wieder und wieder und wieder und wieder...) betrittst. Hinzu kommt die Frage ob rekursiv ein Problem sein koennte oder nicht (werden mehr als ~65k `GDTO`s untereinander sein?).

Etwas Pseudo-Code dazu:

Java:
private void addGdtosToList(GDTO gdto, List<GDTO> targetList) {
    for (GDTO nestedGdto : gdto) {
        targetList.add(nestedGdto);
       
        addGdtosToList(nestedGdto, targetList);
    }
}

In dem Fall wird der Parameter targetList uebergeben um zu verhindern dass man viele Instanzen einer Liste erzeugt nur um sie gleich wieder zu verwerfen. Wenn die Sache ein ungerichteter Graph ist, dann musst du stattdessen am besten ein Set als Ziel verwenden, und pruefen ob dieses GDTO bereits im Set vorkommt.
 
Du meinst
Java:
for (GDTO nestedGdto : gdto.getG()) {

anstelle von
Java:
for (GDTO nestedGdto : gdto) {
 
Man könnte z. B. auch darüber nachdenken, einen generischen Iterator zu basteln:
Java:
public class RecursiveIterator<T> implements Iterator<T> {
    private final Function<T, Collection<? extends T>> childMapper;
    private final Deque<T> stack;

    public RecursiveIterator(T root, Function<T, Collection<? extends T>> childMapper) {
        this.stack = new ArrayDeque<>();
        this.childMapper = childMapper;
        push(root);
    }

    private void push(T elem) {
        if (elem != null) {
            stack.push(elem);
        }
    }

    public boolean hasNext() {
        return !stack.isEmpty();
    }

    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        T result = stack.pop();
        for (T child : childMapper.apply(result)) {
            push(child);
        }
        return result;
    }
}

Dem Konstruktor gibt man das Root-Element und eine Funktion mit, die von einem gegebenen Objekt die Kindobjekte ermittelt.

Java:
RecursiveIterator<GDTO> it = new RecursiveIterator<>(root, node -> node.getG());
 

Neue Themen


Zurück
Oben