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