итератор над вложенными коллекциями - PullRequest
3 голосов
/ 19 февраля 2010

У меня есть две структуры данных в Java:
Один называется DebateAssignment и имеет 5 объектов DebateTeam, каждый из которых связан с определенным перечислением, включающим

{JUDGE, PROP1, PROP2, OP1, OP2}

В другом классе я использую List<DebateAssignment>, и я хочу создать итератор, который будет указывать на конкретный DebateTeam в определенном назначении Debate, и я хочу, чтобы он перебирал все команды по всем назначениям, переходя от задания к назначению без проблем.

Как бы я поступил так?

Ответы [ 4 ]

5 голосов
/ 19 февраля 2010

В одну сторону, используя google-collection / guava :

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

Другой способ - сохранить данные как Multimap<DebateAssignment, DebateTeam>, а затем просто выполнить итерацию по представлению values() или entries(). Эта структура данных не будет моделировать JUDGE / PROP1 / etc. ассоциация, хотя.

4 голосов
/ 19 февраля 2010

Предполагая, что DebateAssignment имеет что-то вроде

public Collection<DebateTeam> getDebateTeams();

Вы хотите Iterator<DebateTeam>?

Если это так, вы хотите что-то вроде:

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...
}
2 голосов
/ 19 февраля 2010

Вероятно, самый простой подход:

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

Конечно, вы могли бы написать новый класс, который реализует Iterator<DebateTeam>, который "сглаживает" вложенные итераторы, но это несколько усложняется, поскольку вам придется явно отслеживать оба итератора ... (подробности см. В ответе Клинтона это).

0 голосов
/ 19 февраля 2010

Вы можете расширить реализацию списка, например ArrayList, и добавить метод для возврата реализации Iterator, которая делает то, что вы хотите.

Переопределение метода iterator () может не являться опцией для общего типа возвращаемого им итератора.

...