1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.collections4.iterators; 18 19 import java.lang.reflect.Array; 20 import java.util.NoSuchElementException; 21 22 import org.apache.commons.collections4.ResettableIterator; 23 24 /** 25 * Implements an {@link java.util.Iterator Iterator} over any array. 26 * <p> 27 * The array can be either an array of object or of primitives. If you know 28 * that you have an object array, the 29 * {@link org.apache.commons.collections4.iterators.ObjectArrayIterator ObjectArrayIterator} 30 * class is a better choice, as it will perform better. 31 * <p> 32 * The iterator implements a {@link #reset} method, allowing the reset of 33 * the iterator back to the start if required. 34 * 35 * @param <E> the type of elements returned by this iterator. 36 * @since 1.0 37 */ 38 public class ArrayIterator<E> implements ResettableIterator<E> { 39 40 /** The array to iterate over */ 41 final Object array; 42 /** The start index to loop from */ 43 final int startIndex; 44 /** The end index to loop to */ 45 final int endIndex; 46 /** The current iterator index */ 47 int index; 48 49 /** 50 * Constructs an ArrayIterator that will iterate over the values in the 51 * specified array. 52 * 53 * @param array the array to iterate over. 54 * @throws IllegalArgumentException if {@code array} is not an array. 55 * @throws NullPointerException if {@code array} is {@code null} 56 */ 57 public ArrayIterator(final Object array) { 58 this(array, 0); 59 } 60 61 /** 62 * Constructs an ArrayIterator that will iterate over the values in the 63 * specified array from a specific start index. 64 * 65 * @param array the array to iterate over. 66 * @param startIndex the index to start iterating at. 67 * @throws IllegalArgumentException if {@code array} is not an array. 68 * @throws NullPointerException if {@code array} is {@code null} 69 * @throws IndexOutOfBoundsException if the index is invalid 70 */ 71 public ArrayIterator(final Object array, final int startIndex) { 72 this(array, startIndex, Array.getLength(array)); 73 } 74 75 /** 76 * Constructs an ArrayIterator that will iterate over a range of values 77 * in the specified array. 78 * 79 * @param array the array to iterate over. 80 * @param startIndex the index to start iterating at. 81 * @param endIndex the index to finish iterating at. 82 * @throws IllegalArgumentException if {@code array} is not an array. 83 * @throws NullPointerException if {@code array} is {@code null} 84 * @throws IndexOutOfBoundsException if either index is invalid 85 */ 86 public ArrayIterator(final Object array, final int startIndex, final int endIndex) { 87 this.array = array; 88 this.startIndex = startIndex; 89 this.endIndex = endIndex; 90 this.index = startIndex; 91 92 final int len = Array.getLength(array); 93 checkBound(startIndex, len, "start"); 94 checkBound(endIndex, len, "end"); 95 if (endIndex < startIndex) { 96 throw new IllegalArgumentException("End index must not be less than start index."); 97 } 98 } 99 100 /** 101 * Checks whether the index is valid or not. 102 * 103 * @param bound the index to check 104 * @param len the length of the array 105 * @param type the index type (for error messages) 106 * @throws IndexOutOfBoundsException if the index is invalid 107 */ 108 protected void checkBound(final int bound, final int len, final String type ) { 109 if (bound > len) { 110 throw new ArrayIndexOutOfBoundsException( 111 "Attempt to make an ArrayIterator that " + type + 112 "s beyond the end of the array. " 113 ); 114 } 115 if (bound < 0) { 116 throw new ArrayIndexOutOfBoundsException( 117 "Attempt to make an ArrayIterator that " + type + 118 "s before the start of the array. " 119 ); 120 } 121 } 122 123 // Properties 124 /** 125 * Gets the array that this iterator is iterating over. 126 * 127 * @return the array this iterator iterates over. 128 */ 129 public Object getArray() { 130 return array; 131 } 132 133 /** 134 * Gets the end index to loop to. 135 * 136 * @return the end index 137 * @since 4.0 138 */ 139 public int getEndIndex() { 140 return this.endIndex; 141 } 142 143 /** 144 * Gets the start index to loop from. 145 * 146 * @return the start index 147 * @since 4.0 148 */ 149 public int getStartIndex() { 150 return this.startIndex; 151 } 152 153 // Iterator interface 154 /** 155 * Returns true if there are more elements to return from the array. 156 * 157 * @return true if there is a next element to return 158 */ 159 @Override 160 public boolean hasNext() { 161 return index < endIndex; 162 } 163 164 /** 165 * Returns the next element in the array. 166 * 167 * @return the next element in the array 168 * @throws NoSuchElementException if all the elements in the array 169 * have already been returned 170 */ 171 @Override 172 @SuppressWarnings("unchecked") 173 public E next() { 174 if (!hasNext()) { 175 throw new NoSuchElementException(); 176 } 177 return (E) Array.get(array, index++); 178 } 179 180 /** 181 * Throws {@link UnsupportedOperationException}. 182 * 183 * @throws UnsupportedOperationException always 184 */ 185 @Override 186 public void remove() { 187 throw new UnsupportedOperationException("remove() method is not supported"); 188 } 189 190 /** 191 * Resets the iterator back to the start index. 192 */ 193 @Override 194 public void reset() { 195 this.index = this.startIndex; 196 } 197 198 }