N.Bhat
N.Bhat

Reputation: 3

how to iterate on every second element in java

I tried to work this out but couldn't.

I need to implement a class which implements iterator and takes iterator as constructor parameter,

1)Need to return every 2nd hasnext

2)Need to return every 2nd next element

Basically I am trying to make use of given iterator received from constructor, But when i use next element on hasnext I am actually increasing the iterator by one element. so problem comes when i independently access hasNext or next element and does not pass all the test cases. Any solution or idea on this

Template and my expected implementation looks like below:

public class AlternateIterator<T> implements Iterator<T>
public AlternateIterator(Iterator<T> target)

public boolean hasNext() {
        boolean returnvalue = false;
                if(iterator.hasNext()) {
                    iterator.next();
                    returnvalue = iterator.hasNext();
                }
                return returnvalue;

    }

    @Override
    public T next() {
        T object = null;
        if(iterator.hasNext()) {
        object  = iterator.next();
        return object;
        }
        else
            return null;

-- Gone through this link but it creates a new implementation itself while i want to use the given template only:

Can we write our own iterator in Java?

Upvotes: 0

Views: 3556

Answers (3)

David Ehrmann
David Ehrmann

Reputation: 7576

Your issue is that hasNext() changes the state of the decorated Iterator. You need a member variable like skipped to track state so that hasNext() won't double-advance and skip two, and your implementation of next() should use this.hasNext(), not iterator.hasNext().

Edit: it'll look something like this:

public class AlternateIterator<T> implements Iterator<T> {
    public AlternateIterator(Iterator<T> target) { ... }

    private volatile boolean skipped = false;

    public boolean hasNext() {
        if (!skipped) {
            skipped = true;
            if (iterator.hasNext()) {
                iterator.next();
            }
        }
        return iterator.hasNext();
    }

    @Override
    public T next() {
        hasNext();
        skipped = false;
        return iterator.next();
    }
}

Upvotes: 0

erickson
erickson

Reputation: 269677

Track whether you've skipped the element from the source iterator or not, like this:

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;

final class AlternateIterator<T>
  implements Iterator<T>
{

  static <T> Iterable<T> alternate(Iterable<T> original)
  {
    return () -> new AlternateIterator<>(original.iterator());
  }

  private final Iterator<T> source;

  private boolean skipped;

  AlternateIterator(Iterator<T> source)
  {
    this.source = Objects.requireNonNull(source);
  }

  @Override
  public boolean hasNext()
  {
    if (!skipped) {
      if (source.hasNext())
        source.next();
      skipped = true;
    }
    return source.hasNext();
  }

  @Override
  public T next()
  {
    if (hasNext()) {
      skipped = false;
      return source.next();
    }
    throw new NoSuchElementException();
  }

  @Override
  public void remove()
  {
    source.remove();
  }

}

Upvotes: 1

garnulf
garnulf

Reputation: 366

You need to have a boolean member which stores if hasNext has been called since the last call of next. This way you know if you need to call an additional next or not in both methods.

Upvotes: 0

Related Questions