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 * <p> 33 * The iterator implements a {@link #reset} method, allowing the reset of 34 * the iterator back to the start if required. 35 * </p> 36 * 37 * @param <E> the type of elements returned by this iterator. 38 * @since 1.0 39 */ 40 public class ArrayIterator<E> implements ResettableIterator<E> { 41 42 /** The array to iterate over */ 43 final Object array; 44 /** The start index to loop from */ 45 final int startIndex; 46 /** The end index to loop to */ 47 final int endIndex; 48 /** The current iterator index */ 49 int index; 50 51 /** 52 * Constructs an ArrayIterator that will iterate over the values in the 53 * specified array. 54 * 55 * @param array the array to iterate over. 56 * @throws IllegalArgumentException if {@code array} is not an array. 57 * @throws NullPointerException if {@code array} is {@code null} 58 */ 59 public ArrayIterator(final Object array) { 60 this(array, 0); 61 } 62 63 /** 64 * Constructs an ArrayIterator that will iterate over the values in the 65 * specified array from a specific start index. 66 * 67 * @param array the array to iterate over. 68 * @param startIndex the index to start iterating at. 69 * @throws IllegalArgumentException if {@code array} is not an array. 70 * @throws NullPointerException if {@code array} is {@code null} 71 * @throws IndexOutOfBoundsException if the index is invalid 72 */ 73 public ArrayIterator(final Object array, final int startIndex) { 74 this(array, startIndex, Array.getLength(array)); 75 } 76 77 /** 78 * Constructs an ArrayIterator that will iterate over a range of values 79 * in the specified array. 80 * 81 * @param array the array to iterate over. 82 * @param startIndex the index to start iterating at. 83 * @param endIndex the index to finish iterating at. 84 * @throws IllegalArgumentException if {@code array} is not an array. 85 * @throws NullPointerException if {@code array} is {@code null} 86 * @throws IndexOutOfBoundsException if either index is invalid 87 */ 88 public ArrayIterator(final Object array, final int startIndex, final int endIndex) { 89 this.array = array; 90 this.startIndex = startIndex; 91 this.endIndex = endIndex; 92 this.index = startIndex; 93 94 final int len = Array.getLength(array); 95 checkBound(startIndex, len, "start"); 96 checkBound(endIndex, len, "end"); 97 if (endIndex < startIndex) { 98 throw new IllegalArgumentException("End index must not be less than start index."); 99 } 100 } 101 102 /** 103 * Checks whether the index is valid or not. 104 * 105 * @param bound the index to check 106 * @param len the length of the array 107 * @param type the index type (for error messages) 108 * @throws IndexOutOfBoundsException if the index is invalid 109 */ 110 protected void checkBound(final int bound, final int len, final String type) { 111 if (bound > len) { 112 throw new ArrayIndexOutOfBoundsException("Attempt to make an ArrayIterator that " + type + "s beyond the end of the array. "); 113 } 114 if (bound < 0) { 115 throw new ArrayIndexOutOfBoundsException("Attempt to make an ArrayIterator that " + type + "s before the start of the array. "); 116 } 117 } 118 119 /** 120 * Gets the array that this iterator is iterating over. 121 * 122 * @return the array this iterator iterates over. 123 */ 124 public Object getArray() { 125 return array; 126 } 127 128 /** 129 * Gets the end index to loop to. 130 * 131 * @return the end index 132 * @since 4.0 133 */ 134 public int getEndIndex() { 135 return endIndex; 136 } 137 138 /** 139 * Gets the start index to loop from. 140 * 141 * @return the start index 142 * @since 4.0 143 */ 144 public int getStartIndex() { 145 return startIndex; 146 } 147 148 /** 149 * Returns true if there are more elements to return from the array. 150 * 151 * @return true if there is a next element to return 152 */ 153 @Override 154 public boolean hasNext() { 155 return index < endIndex; 156 } 157 158 /** 159 * Returns the next element in the array. 160 * 161 * @return the next element in the array 162 * @throws NoSuchElementException if all the elements in the array 163 * have already been returned 164 */ 165 @Override 166 @SuppressWarnings("unchecked") 167 public E next() { 168 if (!hasNext()) { 169 throw new NoSuchElementException(); 170 } 171 return (E) Array.get(array, index++); 172 } 173 174 /** 175 * Throws {@link UnsupportedOperationException}. 176 * 177 * @throws UnsupportedOperationException always 178 */ 179 @Override 180 public void remove() { 181 throw new UnsupportedOperationException("remove() method is not supported"); 182 } 183 184 /** 185 * Resets the iterator back to the start index. 186 */ 187 @Override 188 public void reset() { 189 index = startIndex; 190 } 191 192 }