开发者

iterator over nested collections

I have two data structures in Java:

One is called DebateAssignment and has 5 DebateTeam objects, each associated with a specific enum that includes

{JUDGE, PROP1, PROP2, OP1, OP2}

In 开发者_JAVA百科another class I use List<DebateAssignment> and I want to create an iterator that will point to a specific DebateTeam in a specific DebateAssignment and I want it to iterate over all teams over all assignments, going from an assignment to assignment seamlessly.

How would I go about doing that?


One way, using google-collections / guava:

return Iterables.concat(Iterables.transform(assignments,
    new Function<DebateAssigment, Collection<DebateTeam>>() {
      public Collection<DebateTeam> apply(DebateAssignment assignment) {
        return assignment.getDebateTeams();
      }
    }));

Another way is to store the data as a Multimap<DebateAssignment, DebateTeam>, then simply iterate over either the values() or entries() view. That data structure won't model the JUDGE/PROP1/etc. association, though.


Assuming DebateAssignment has something like

public Collection<DebateTeam> getDebateTeams();

You want an Iterator<DebateTeam>?

If so, would you want something like:

public class DebateTeamIterator implements Iterator<DebateTeam> {
    private Iterator<DebateAssignment> iAssignment;
    private Iterator<DebateTeam> iTeam;

    public DebateTeamIterator(Iterator<DebateTeam> iAssignment) {
        this.iAssignment = iAssignment;
        if (iAssignment.hasNext())
            iTeam = iAssignment.next().getDebateTeams().iterator();
        else
            iTeam = new LinkedList<DebateTeam>().iterator();
    }

    public boolean hasNext() {
       return iTeam.hasNext() || iAssignment.hasNext();
    }

    public DebateTeam next() {
        if (!iTeam.hasNext())
            iTeam = iAssignment.next().getDebateTeams().iterator();
        return iTeam.next();
    }

    // ... other methods removed for brevity...
}


Probably the easiest approach is:

List<DebateAssignment> list = ...
List<DebateTeam> dtList = new ArrayList<DebateTeam>();
for (DebateAssignment da : list) {
    dtList.addAll(da.getTeams());
}
return dtList.iterator();

Of course you could write a new class that implements Iterator<DebateTeam> that "flattens" nested iterators, but that is somewhat involved, as you will have to explicitly keep track of both iterators ... (see Clinton's answer for details on this).


You can extend a list implementation like ArrayList and add a method to return an Iterator implementation which does what you want.

Overriding the iterator() method may not be an option doe to the generic type of the iterator returned by it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜