001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.iterators; 018 019import java.lang.reflect.Array; 020import java.util.NoSuchElementException; 021 022import org.apache.commons.collections4.ResettableIterator; 023 024/** 025 * Implements an {@link java.util.Iterator Iterator} over any array. 026 * <p> 027 * The array can be either an array of object or of primitives. If you know 028 * that you have an object array, the 029 * {@link org.apache.commons.collections4.iterators.ObjectArrayIterator ObjectArrayIterator} 030 * class is a better choice, as it will perform better. 031 * </p> 032 * <p> 033 * The iterator implements a {@link #reset} method, allowing the reset of 034 * the iterator back to the start if required. 035 * </p> 036 * 037 * @param <E> the type of elements returned by this iterator. 038 * @since 1.0 039 */ 040public class ArrayIterator<E> implements ResettableIterator<E> { 041 042 /** The array to iterate over */ 043 final Object array; 044 /** The start index to loop from */ 045 final int startIndex; 046 /** The end index to loop to */ 047 final int endIndex; 048 /** The current iterator index */ 049 int index; 050 051 /** 052 * Constructs an ArrayIterator that will iterate over the values in the 053 * specified array. 054 * 055 * @param array the array to iterate over. 056 * @throws IllegalArgumentException if {@code array} is not an array. 057 * @throws NullPointerException if {@code array} is {@code null} 058 */ 059 public ArrayIterator(final Object array) { 060 this(array, 0); 061 } 062 063 /** 064 * Constructs an ArrayIterator that will iterate over the values in the 065 * specified array from a specific start index. 066 * 067 * @param array the array to iterate over. 068 * @param startIndex the index to start iterating at. 069 * @throws IllegalArgumentException if {@code array} is not an array. 070 * @throws NullPointerException if {@code array} is {@code null} 071 * @throws IndexOutOfBoundsException if the index is invalid 072 */ 073 public ArrayIterator(final Object array, final int startIndex) { 074 this(array, startIndex, Array.getLength(array)); 075 } 076 077 /** 078 * Constructs an ArrayIterator that will iterate over a range of values 079 * in the specified array. 080 * 081 * @param array the array to iterate over. 082 * @param startIndex the index to start iterating at. 083 * @param endIndex the index to finish iterating at. 084 * @throws IllegalArgumentException if {@code array} is not an array. 085 * @throws NullPointerException if {@code array} is {@code null} 086 * @throws IndexOutOfBoundsException if either index is invalid 087 */ 088 public ArrayIterator(final Object array, final int startIndex, final int endIndex) { 089 this.array = array; 090 this.startIndex = startIndex; 091 this.endIndex = endIndex; 092 this.index = startIndex; 093 094 final int len = Array.getLength(array); 095 checkBound(startIndex, len, "start"); 096 checkBound(endIndex, len, "end"); 097 if (endIndex < startIndex) { 098 throw new IllegalArgumentException("End index must not be less than start index."); 099 } 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}