View Javadoc
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  }