0

Suppose you have given a class in Java that extends the Iterable interface. This class has to provide an Iterator that should return the instance of the surrounding class, take a look at the main method.

public class Test implements Iterable<Test> {

    @Override
    public Iterator<Test> iterator() {

        return new Iterator<Test>() {
          private boolean onlyOnce = false;

            @Override
            public boolean hasNext() {
                return false;
            }

            @Override
            public Test next() {         
               if (!onlyOnce) {
                 onlyOnce = true;
                 // TODO return
               } 
               throw new NoSuchElementException("Iterator has already been called");
            }
        };
    }
    public static void main(String[] args) {

        Test test = new Test();
        Test test2 = test.iterator().next();

        boolean b = test == test2; // should be true
    }

}

How could this issue be solved in Java?

mrbela
  • 4,477
  • 9
  • 44
  • 79
  • 2
    Really unclear what you're trying to achieve... but... `return Test.this;`? – Andy Turner Jan 23 '20 at 15:59
  • I'm not even sure what "this issue" is. It makes no sense to iterate over an object that you already have. I think an XY Problem is at work here. – markspace Jan 23 '20 at 16:01
  • This doesn't make sense, so not sure what you're trying to do. Did you forget something? `// TODO return` – Christopher Schneider Jan 23 '20 at 16:02
  • `hasNext()` should return `true` the first time it is called; thereafter it should return `false`. So make it return `!onlyOnce`. Or invert the polarity of `onlyOnce` (call it `firstTime` and initialise it to `true`). – DodgyCodeException Jan 23 '20 at 16:04

1 Answers1

3

In order to return the enclosing instance of Test, use a qualified this:

return Test.this;

However, a much neater way to implement the method would be to use an existing iterator implementation:

@Override
public Iterator<Test> iterator() {
  return Arrays.asList(this).iterator();
  // or Collections.singleton(this).iterator()
  // or Stream.of(this).iterator()
  // or many other possibilities.
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 3
    Might also consider `Collections.singleton(this).iterator()` which wouldn't even have to allocate an array. – Mark Peters Jan 23 '20 at 16:15
  • Thank you! Didn't know the opportunity of getting the enclosing instance of a type, like "Test.this". How is this "operator/technique" called? Is it a newer feature of Java? – mrbela Jan 23 '20 at 16:22
  • 1
    @mrbela as stated in the answer, it's a ["qualified this"](https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.8.4). No, it is not new. – Andy Turner Jan 23 '20 at 16:24
  • @AndyTurner any idea about my issue here : https://stackoverflow.com/questions/59885424/how-to-stop-incessant-crash-on-search-filter-in-android-recyclerview?noredirect=1#comment105900073_59885424 –  Jan 23 '20 at 20:41