Randhir
Randhir

Reputation: 314

How to iterate over alternative elements using an iterator?

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

The above code will iterate sequentially 1 through 6. Can we iterate the same list alternatively so that it will print 1, 3, 5 without changing the while loop?

Upvotes: 6

Views: 5875

Answers (9)

Spartan
Spartan

Reputation: 61

Iterator implementation that wraps an already existing iterator. It provides the logically correct definition of hasNext() method for alternate iterator as the hasNext() method should return true only if the alternate position number is present.

    import java.util.Iterator;

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

        private T next;
        private Iterator<T> it;

        public AlternateIterator(Iterator<T> it) {
            this.it = it;
            next = null;
        }
        // Logically hasNext() of this iterator should return true only if it has a valid alternate element present.
        @Override
        public boolean hasNext() {
            if(next != null) {
                return true;
            }
            if(it.hasNext()) {
                it.next();
                if(it.hasNext()) {
                    next = it.next();
                    return true;
                }
            }
            return false;
        }

        @Override
        public T next() {
            if(next != null) {
                T temp = next;
                next = null;
                return temp;
            }
            else {
                if(hasNext())
                    return next();
                else
                    return null;
            }
        }
    }

Upvotes: 1

Sweeper
Sweeper

Reputation: 270995

You only want to print the odd numbers? Filter the list with a stream:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Iterator<Integer> it = list.stream().filter(x -> x % 2 == 1).iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

Edit:

if you want to get every other element then using streams will be less appropriate, but you can still do it:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
int limit = list.size() / 2 - (1 - list.size() % 2);
Iterator<Integer> it = IntStream.iterate(0, x -> x + 2).limit(limit).map(list::get).iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

I recommend daniu's solution.

Upvotes: 7

Nikhil
Nikhil

Reputation: 3950

A very simple code goes like this:

List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Iterator it = list.iterator();
while(it.hasNext()){
   static int i=0;
    if(i%2==0){
    System.out.println(it.next());
     }
     i+=1;
}

Upvotes: -1

sprinter
sprinter

Reputation: 27946

A simple mechanism is to just use the index of the list items:

IntStream.range(0, list.size())
    .filter(i -> i % 2 == 0)
    .mapToObj(list::get)
    .forEach(System.out::println);

And if you particularly want an iterator, just call iterator() instead of forEach.

Upvotes: 7

Eugene
Eugene

Reputation: 120848

I think that the java-8 way to do it would be something like this:

class Skipping extends AbstractSpliterator<Integer> {

    private List<Integer> list;
    private int index = 0;

    public Skipping(List<Integer> list) {
        super(list.size() / 2, 0);
        this.list = new ArrayList<>(list);
    }

    @Override
    public boolean tryAdvance(Consumer<? super Integer> action) {
        if (index != list.size()) {
            if (index % 2 == 0) {
                action.accept(list.get(index++));
            }
            ++index;
            return true;
        }
        return false;
    }

}

And usage:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Iterator<Integer> iter = StreamSupport.stream(new Skipping(list), false).iterator();

Upvotes: 4

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

Create your own custom iterator from any underlying iterator:

class TwoStepsAtOnceIterator<E> implements Iterator<E> {
    private Iterator<E> internal;
    public TwoStepsAtOnceIterator(Iterator<E> it) {
      internal = it;
    }
    public boolean hasNext() {
      return internal.hasNext();
    }
    public E next() {
      // problem not specified when underlying sequence has odd number of elements
      internal.next();
      return internal.next();
    }
    public void remove() {
      throw new UnsupportedOperationException();
    }
}

Upvotes: 0

Lino
Lino

Reputation: 19926

You could create an Iterator implementation that wraps an already existant iterator:

class IteratorWrapper<T> implements Iterator<T> {
    private final Iterator<? extends T> iterator;

    public IteratorWrapper(Iterator<? extends T> iterator){
        this.iterator = iterator;
    }

    public boolean hasNext(){
        return iterator.hasNext();
    }

    public T next(){
        final T next = iterator.next();
        if(iterator.hasNext()){
            iterator.next();
        }
        return next;
    }

    public void remove(){
        iterator.remove();
    }
} 

making your code the following:

List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Iterator<Iterator> it = new IteratorWrapper<>(list.iterator());
while(it.hasNext()){
    System.out.println(it.next());
}

Upvotes: 1

daniu
daniu

Reputation: 14999

Create your own Iterator.

class SkippingIterator<T> implements Iterator<T> {
    private List<T> list;
    private currentPosition;
    private int skipBy;
    public SkippingIterator(List<T> l) {
        this(l, 2);
    }
    public SkippingIterator(List<T> l, int skip) {
        this(l, skipBy, 0);
    }
    public SkippingIterator(List<T> l, int skip, int startPosition) {
        list = l;
        skipBy = skip;
        currentPosition = startPosition;
    }
    public boolean hasNext() {
        return currentPosition < list.size();
    }
    public T next() {
        T result = list.get(currentPosition);
        currentPosition += skip;
        return result;
    }
}

making your code

List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Iterator it = new SkippingIterator<>(list);
while(it.hasNext()){
    System.out.println(it.next());
}

Upvotes: 13

Eran
Eran

Reputation: 393781

Yes, you can. Inside the while loop's body, check if the iterator has a next element, and if it does, advance the iterator again. This will cause the even elements not to be printed.

List<Integer> list=Arrays.asList(1,2,3,4,5,6);
Iterator it=list.iterator();
while (it.hasNext()){
    System.out.println(it.next());
    if (it.hasNext()) {
        it.next();
    }
}

Upvotes: 5

Related Questions