Reputation: 314
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
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
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
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
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
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
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
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
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
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