@Override
  default Iterator<Result> iterator() {
    return new Iterator<Result>() {
      // The next RowResult, possibly pre-read
      Result next = null;

      // return true if there is another item pending, false if there isn't.
      // this method is where the actual advancing takes place, but you need
      // to call next() to consume it. hasNext() will only advance if there
      // isn't a pending next().
      @Override
      public boolean hasNext() {
        if (next != null) {
          return true;
        }
        try {
          return (next = ResultScanner.this.next()) != null;
        } catch (IOException e) {
          throw new UncheckedIOException(e);
        }
      }

      // get the pending next item and advance the iterator. returns null if
      // there is no next item.
      @Override
      public Result next() {
        // since hasNext() does the real advancing, we call this to determine
        // if there is a next before proceeding.
        if (!hasNext()) {
          return null;
        }

        // if we get to here, then hasNext() has given us an item to return.
        // we want to return the item and then null out the next pointer, so
        // we use a temporary variable.
        Result temp = next;
        next = null;
        return temp;
      }
    };
  }
Interface for client-side scanning. Go to {@link Table} to obtain instances.
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ResultScanner.java