user5562650
user5562650

Reputation: 189

How can I iterate throughout on list of nested java objects?

I have an object class which is contains a list of itself... Something like this:

public class SearchItemType implements Serializable {
  protected List<SearchItemType> childItem;
}

The childItem also can conatain list of child items. My question is, can I iterate over childItems in all levels?

Right now my code looks like this:

public SearchItemType getElementByOpenedRowID(SearchItemType gridResult, String selectedRowId, Boolean found) {
        SearchItemType element = new SearchItemType();

        if (gridResult.getId().equals(selectedRowId)) {
            element = gridResult;
            found = true;
        }

        for (SearchItemType child : gridResult.getChildItem()) {
            if (child.getId().equals(selectedRowId)) {
                element = child;
                found = true;
                break;
            }
        }
        if (!found) {
            for (SearchItemType child : gridResult.getChildItem()) {
                element = getElementByOpenedRowID(child, selectedRowId, found);
                checkChildID(child, selectedRowId);
                if (element != null) break;
            }
        }
        return element;
    }

Many thanks.

Upvotes: 0

Views: 3597

Answers (5)

Lucio Menci
Lucio Menci

Reputation: 143

I played around by creating an iterator.

See this:

public class SearchItemType {
    protected List<SearchItemType> childItem = new ArrayList();
    protected String id;

    public SearchItemType(String id) {
        this.id = id;
    }

    public static void main(String[] args) {
        SearchItemType one = new SearchItemType("1");
        SearchItemType one_one = new SearchItemType("1.1");
        SearchItemType one_two = new SearchItemType("1.2");
        SearchItemType one_three = new SearchItemType("1.3");
        SearchItemType one_four = new SearchItemType("1.4");
        SearchItemType one_two_one = new SearchItemType("1.2.1");
        SearchItemType one_two_two = new SearchItemType("1.2.2");
        SearchItemType one_two_three = new SearchItemType("1.2.3");
        SearchItemType one_three_one = new SearchItemType("1.3.1");
        SearchItemType one_three_two = new SearchItemType("1.3.2");
        SearchItemType one_three_three = new SearchItemType("1.3.3");
        SearchItemType one_three_two_one = new SearchItemType("1.3.2.1");
        SearchItemType one_three_two_two = new SearchItemType("1.3.2.2");
        one.childItem.add(one_one);
        one.childItem.add(one_two);
        one.childItem.add(one_three);
        one.childItem.add(one_four);
        one_two.childItem.add(one_two_one);
        one_two.childItem.add(one_two_two);
        one_two.childItem.add(one_two_three);
        one_three.childItem.add(one_three_one);
        one_three.childItem.add(one_three_two);
        one_three.childItem.add(one_three_three);
        one_three_two.childItem.add(one_three_two_one);
        one_three_two.childItem.add(one_three_two_two);

        Iterator<SearchItemType> itr = one.getItemTypeIterator();
        while (itr.hasNext())
            System.out.println(itr.next().id);
    }

    public Iterator<SearchItemType> getItemTypeIterator() {
        return new Iterator<SearchItemType>() {
            ArrayList<SearchItemType> parents = new ArrayList();
            SearchItemType next = null;
            boolean avoidChildren = false, nextSearched = false;

            public boolean hasNext() {
                if (!nextSearched)
                    searchNext();
                nextSearched = true;
                return next != null;
            }

            public SearchItemType next() {
                if (!nextSearched)
                    searchNext();
                nextSearched = false;
                return next;
            }

            private void searchNext() {
                if (next == null) {
                    next = SearchItemType.this;
                    return;
                }

                if (!avoidChildren) {
                    if (next.childItem.size() > 0) {
                        parents.add(next);
                        next = next.childItem.get(0);
                    } else {
                        avoidChildren = true;
                    }
                }

                if (avoidChildren) {
                    while (parents.size() > 0) {
                        SearchItemType lastParent = parents.get(parents.size() - 1);
                        int i = lastParent.childItem.indexOf(next);
                        if (i < lastParent.childItem.size() - 1) {
                            next = lastParent.childItem.get(i + 1);
                            avoidChildren = false;
                            return;
                        } else {
                            next = lastParent;
                            parents.remove(parents.size() - 1);
                        }
                    }
                    next = null;
                }
            }
        };
    }
}

The result is:

1
1.1
1.2
1.2.1
1.2.2
1.2.3
1.3
1.3.1
1.3.2
1.3.2.1
1.3.2.2
1.3.3
1.4

Upvotes: 0

Billy Brown
Billy Brown

Reputation: 2342

There is one error: at the start of the method, you set SearchItemType element = new SearchItemType(); but then check for null when you recurse. element will never be null. You can fix this by setting it to null at the start, but I have some suggestions about your code:

  • Instead of assigning the found value to an element and setting a found flag, just return the object as soon as you find it. At the end of the method return null. This will be much clearer.
  • Iterating over the children and checking them will currently be executed even if the parent was the one that was searched for. In fact, you can remove this loop entirely, as it is handled by the recursive step below.
  • Why are you passing found as a parameter? If you pass it true, then there is no point in having it, so if you really need it, just instantiate it in the method.
  • Make sure to check that gridResult is not null. You could remedy this by making getElementByOpenedRowID a method on SearchItemType, meaning that gridResult does not need to be passed.

Applying these changes will result in:

public SearchItemType getElementByOpenedRowID(SearchItemType gridResult, String selectedRowId) {
    // stop at null
    if (gridResult == null) {
        return null;
    }
    if (gridResult.getId().equals(selectedRowId)) {
        return gridResult; // return once found
    }

    // check all of the children
    for (SearchItemType child : gridResult.getChildItem()) {
        // do the search again for every child
        SearchItemType result = getElementByOpenedRowID(child, selectedRowId);
        if (result != null) {
            // return once found and sent it all the way to the top
            return result;
        }
    }
    return null;
}

Upvotes: 1

sercanturkmen
sercanturkmen

Reputation: 127

You want to iterate through the children recursively as so:

public SearchItemType getElementByOpenedRowID(SearchItemType gridResult, String selectedRowId) {
    SearchItemType element = null;
    if (gridResult == null) return null;
    else if (gridResult.getId().equals(selectedRowId)) return gridResult;
    else {
        for (SearchItemType child : gridResult.getChildItem()) {
            element = getElementByOpenedRowID(child, selectedRowId);
            if (element != null) break;
        }
    }
    return element;
}

Upvotes: 0

swapnil
swapnil

Reputation: 230

Yes you can iterate on childItem object at any level as long as childItem is not null and object inside it has non-null values.

In Data structure implementation of LinkedList every node in the LinkedList has Data fields link to other nodes (In case of Java it's reference to other nodes).

It's also called as self referencing objects that means object pointing to object of similar type.

As long as you have non-null values in the list you can iterate at any level.

Data structures in Java are implemented in similar manner. Have look at Node class in this code snippet: Linked List implementation using self referencing pointers

Upvotes: 0

B&#225;lint
B&#225;lint

Reputation: 4039

You can do this with recursion:

public void iterate(SearchItemType type) {
    // Do something with type
    for (SearchItemType child in type.childItem) {
        iterate(child);
    }
}

Upvotes: 0

Related Questions