Question

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?

Was it helpful?

Solution

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)

OTHER TIPS

private class Words implements Iterator<String>, Iterable<String> {
  ...
  public Iterator<String> iterator() {
    return this;
  }
  ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top