1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with this 4 * work for additional information regarding copyright ownership. The ASF 5 * licenses this file to You under the Apache License, Version 2.0 (the 6 * "License"); you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law 9 * or agreed to in writing, software distributed under the License is 10 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language 12 * governing permissions and limitations under the License. 13 */ 14 package org.apache.commons.collections4.iterators; 15 16 import java.util.Iterator; 17 18 /** 19 * Decorates another iterator to skip the first N elements. 20 * <p> 21 * In case an offset parameter other than 0 is provided, the decorated 22 * iterator is immediately advanced to this position, skipping all elements 23 * before that position. 24 * </p> 25 * 26 * @since 4.1 27 */ 28 public class SkippingIterator<E> extends AbstractIteratorDecorator<E> { 29 30 /** The offset to bound the first element return */ 31 private final long offset; 32 33 /** The position of the current element */ 34 private long pos; 35 36 //----------------------------------------------------------------------- 37 38 /** 39 * Decorates the specified iterator to skip all elements until the iterator 40 * reaches the position at {@code offset}. 41 * <p> 42 * The iterator is immediately advanced until it reaches the position at {@code offset}, 43 * incurring O(n) time. 44 * 45 * @param iterator the iterator to be decorated 46 * @param offset the index of the first element of the decorated iterator to return 47 * @throws NullPointerException if iterator is null 48 * @throws IllegalArgumentException if offset is negative 49 */ 50 public SkippingIterator(final Iterator<E> iterator, final long offset) { 51 super(iterator); 52 53 if (offset < 0) { 54 throw new IllegalArgumentException("Offset parameter must not be negative."); 55 } 56 57 this.offset = offset; 58 this.pos = 0; 59 init(); 60 } 61 62 /** 63 * Skips the given number of elements. 64 */ 65 private void init() { 66 while (pos < offset && hasNext()) { 67 next(); 68 } 69 } 70 71 //----------------------------------------------------------------------- 72 73 @Override 74 public E next() { 75 final E next = super.next(); 76 pos++; 77 return next; 78 } 79 80 /** 81 * {@inheritDoc} 82 * <p> 83 * In case an offset other than 0 was specified, the underlying iterator will be advanced 84 * to this position upon creation. A call to {@link #remove()} will still result in an 85 * {@link IllegalStateException} if no explicit call to {@link #next()} has been made prior 86 * to calling {@link #remove()}. 87 */ 88 @Override 89 public void remove() { 90 if (pos <= offset) { 91 throw new IllegalStateException("remove() can not be called before calling next()"); 92 } 93 super.remove(); 94 } 95 96 }