Tutorial :iterator over nested collections



Question:

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 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?


Solution:1

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...  }  


Solution:2

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.


Solution:3

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).


Solution:4

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.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »