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.ResettableListIterator; 23 24 /** 25 * Implements a {@link java.util.ListIterator} over an 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 {@link ObjectArrayListIterator} 29 * class is a better choice, as it will perform better. 30 * 31 * <p> 32 * This iterator does not support {@link #add(Object)} or {@link #remove()}, as the array 33 * cannot be changed in size. The {@link #set(Object)} method is supported however. 34 * 35 * @param <E> the type of elements returned by this iterator. 36 * @see org.apache.commons.collections4.iterators.ArrayIterator 37 * @see java.util.Iterator 38 * @see java.util.ListIterator 39 * 40 * @since 3.0 41 */ 42 public class ArrayListIterator<E> extends ArrayIterator<E> 43 implements ResettableListIterator<E> { 44 45 /** 46 * Holds the index of the last item returned by a call to {@code next()} 47 * or {@code previous()}. This is set to {@code -1} if neither method 48 * has yet been invoked. {@code lastItemIndex} is used to implement 49 * the {@link #set} method. 50 */ 51 private int lastItemIndex = -1; 52 53 /** 54 * Constructs an ArrayListIterator that will iterate over the values in the 55 * specified array. 56 * 57 * @param array the array to iterate over 58 * @throws IllegalArgumentException if {@code array} is not an array. 59 * @throws NullPointerException if {@code array} is {@code null} 60 */ 61 public ArrayListIterator(final Object array) { 62 super(array); 63 } 64 65 /** 66 * Constructs an ArrayListIterator that will iterate over the values in the 67 * specified array from a specific start index. 68 * 69 * @param array the array to iterate over 70 * @param startIndex the index to start iterating at 71 * @throws IllegalArgumentException if {@code array} is not an array. 72 * @throws NullPointerException if {@code array} is {@code null} 73 * @throws IndexOutOfBoundsException if the start index is out of bounds 74 */ 75 public ArrayListIterator(final Object array, final int startIndex) { 76 super(array, startIndex); 77 } 78 79 /** 80 * Constructs an ArrayListIterator that will iterate over a range of values 81 * in the specified array. 82 * 83 * @param array the array to iterate over 84 * @param startIndex the index to start iterating at 85 * @param endIndex the index (exclusive) to finish iterating at 86 * @throws IllegalArgumentException if {@code array} is not an array. 87 * @throws IndexOutOfBoundsException if the start or end index is out of bounds 88 * @throws IllegalArgumentException if end index is before the start 89 * @throws NullPointerException if {@code array} is {@code null} 90 */ 91 public ArrayListIterator(final Object array, final int startIndex, final int endIndex) { 92 super(array, startIndex, endIndex); 93 } 94 95 /** 96 * This iterator does not support modification of its backing collection, and so will 97 * always throw an {@link UnsupportedOperationException} when this method is invoked. 98 * 99 * @param o the element to add 100 * @throws UnsupportedOperationException always thrown. 101 * @see java.util.ListIterator#set 102 */ 103 @Override 104 public void add(final Object o) { 105 throw new UnsupportedOperationException("add() method is not supported"); 106 } 107 108 // ListIterator interface 109 /** 110 * Returns true if there are previous elements to return from the array. 111 * 112 * @return true if there is a previous element to return 113 */ 114 @Override 115 public boolean hasPrevious() { 116 return this.index > this.startIndex; 117 } 118 119 /** 120 * Gets the next element from the array. 121 * 122 * @return the next element 123 * @throws NoSuchElementException if there is no next element 124 */ 125 @Override 126 @SuppressWarnings("unchecked") 127 public E next() { 128 if (!hasNext()) { 129 throw new NoSuchElementException(); 130 } 131 this.lastItemIndex = this.index; 132 return (E) Array.get(this.array, this.index++); 133 } 134 135 /** 136 * Gets the next index to be retrieved. 137 * 138 * @return the index of the item to be retrieved next 139 */ 140 @Override 141 public int nextIndex() { 142 return this.index - this.startIndex; 143 } 144 145 /** 146 * Gets the previous element from the array. 147 * 148 * @return the previous element 149 * @throws NoSuchElementException if there is no previous element 150 */ 151 @Override 152 @SuppressWarnings("unchecked") 153 public E previous() { 154 if (!hasPrevious()) { 155 throw new NoSuchElementException(); 156 } 157 this.lastItemIndex = --this.index; 158 return (E) Array.get(this.array, this.index); 159 } 160 161 /** 162 * Gets the index of the item to be retrieved if {@link #previous()} is called. 163 * 164 * @return the index of the item to be retrieved next 165 */ 166 @Override 167 public int previousIndex() { 168 return this.index - this.startIndex - 1; 169 } 170 171 /** 172 * Resets the iterator back to the start index. 173 */ 174 @Override 175 public void reset() { 176 super.reset(); 177 this.lastItemIndex = -1; 178 } 179 180 /** 181 * Sets the element under the cursor. 182 * <p> 183 * This method sets the element that was returned by the last call 184 * to {@link #next()} of {@link #previous()}. 185 * <p> 186 * <b>Note:</b> {@link java.util.ListIterator} implementations that support 187 * {@code add()} and {@code remove()} only allow {@code set()} to be called 188 * once per call to {@code next()} or {@code previous} (see the {@link java.util.ListIterator} 189 * Javadoc for more details). Since this implementation does 190 * not support {@code add()} or {@code remove()}, {@code set()} may be 191 * called as often as desired. 192 * 193 * @param o the element to set 194 * @throws IllegalStateException if {@link #next()} or {@link #previous()} has not been called 195 * before {@link #set(Object)} 196 * @see java.util.ListIterator#set 197 */ 198 @Override 199 public void set(final Object o) { 200 if (this.lastItemIndex == -1) { 201 throw new IllegalStateException("must call next() or previous() before a call to set()"); 202 } 203 204 Array.set(this.array, this.lastItemIndex, o); 205 } 206 207 }