code: public static <T> Iterator<T> filter(Iterator<T> it, Predicate<T> filter) {
          return new Iterator<T>() {
  
              private T cached = null;
  
              @Override
              public boolean hasNext() {
                  if (this.cached != null) {
                      return true;
                  }
  
                  boolean test = false;
                  while (it.hasNext() && !test) {
                      this.cached = it.next();
                      test = filter.test(this.cached);
                  }
                  return test;
              }
  
              @Override
              public T next() {
                  if (!hasNext()) {
                      throw new NoSuchElementException();
                  }
                  final T result = this.cached;
                  this.cached = null;
                  return result;
              }
  
              @Override
              public void remove() {
                  it.remove();
              }
          };
      }
docs: Creates an iterator that returns a filtered view of the input iterator.
  
  @param it The source iterator.
  @param filter The predicate to match elements that should occur in the result.
  @return The filtered iterator.