1

I'm having difficulty using an inner Iterator.

private List<List<? extends HasWord>> sentences = new ArrayList<List<? extends HasWord>>(); 
private Iterator<String> wordIterator = new Words();
private class Words implements Iterator<String> {

    int currSentence = 0;
    int currWord = 0;

    @Override
    public boolean hasNext() {
        return currSentence != sentences.size() - 1 && currWord != sentences.get(currSentence).size() - 1;
    }

    @Override
    public String next() {
        String nextWord = sentences.get(currSentence).get(currWord).word();
        currSentence++;
        currWord++;

        return nextWord;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();          
    }

}

Then, I try to iterate over it:

for (String s : wordIterator) { //Error: Can only iterate over an array or an instance of java.lang.Iterable
            words.add(s);

But it doesn't work. (See commented compiler error on the problematic line). What am I doing wrong here?

On an engineering note, do is the right way to solve my problem? I have a bunch of loops of this form:

    for (List<? extends HasWord> sent : sentences) {
        for (HasWord token : sent) {
            //do stuff
        }
        }

So I decided an Iterator would be cleaner. Is this overkill, or is there another way you'd do it?

2 Answers 2

5

There's nothing fundamentally wrong with having two nested for loops to do this, but I think this would be cleaner:

public class Words implements Iterator<String> {
  private final Iterator<HasWord> sentences;
  private Iterator<String> currentSentence;

  public boolean hasNext() {
    return currentSentence.hasNext() || sentences.hasNext();
  }

  public String next() {
    if (currentSentence.hasNext()) {
      return currentSentence.next();
    }
    currentSentence = sentences.next();
    return next(); // will return the first word of the next sentence
  }
  //remove() omitted for brevity
}

Return a new instance of this class every time you need an iterator over several sentences, and initialize the sentences field using sentences.iterator();

(Edited after reading your question more carefully)

Sign up to request clarification or add additional context in comments.

1 Comment

Note that you may have to add some additional checking if sentences can be empty.
3
private class Words implements Iterator<String>, Iterable<String> {
  ...
  public Iterator<String> iterator() {
    return this;
  }
  ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.