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.ResettableListIterator; 023 024/** 025 * Implements a {@link java.util.ListIterator} over an 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 {@link ObjectArrayListIterator} 029 * class is a better choice, as it will perform better. 030 * </p> 031 * <p> 032 * This iterator does not support {@link #add(Object)} or {@link #remove()}, as the array 033 * cannot be changed in size. The {@link #set(Object)} method is supported however. 034 * </p> 035 * 036 * @param <E> the type of elements returned by this iterator. 037 * @see org.apache.commons.collections4.iterators.ArrayIterator 038 * @see java.util.Iterator 039 * @see java.util.ListIterator 040 * @since 3.0 041 */ 042public class ArrayListIterator<E> extends ArrayIterator<E> 043 implements ResettableListIterator<E> { 044 045 /** 046 * Holds the index of the last item returned by a call to {@code next()} 047 * or {@code previous()}. This is set to {@code -1} if neither method 048 * has yet been invoked. {@code lastItemIndex} is used to implement 049 * the {@link #set} method. 050 */ 051 private int lastItemIndex = -1; 052 053 /** 054 * Constructs an ArrayListIterator that will iterate over the values in the 055 * specified array. 056 * 057 * @param array the array to iterate over 058 * @throws IllegalArgumentException if {@code array} is not an array. 059 * @throws NullPointerException if {@code array} is {@code null} 060 */ 061 public ArrayListIterator(final Object array) { 062 super(array); 063 } 064 065 /** 066 * Constructs an ArrayListIterator that will iterate over the values in the 067 * specified array from a specific start index. 068 * 069 * @param array the array to iterate over 070 * @param startIndex the index to start iterating at 071 * @throws IllegalArgumentException if {@code array} is not an array. 072 * @throws NullPointerException if {@code array} is {@code null} 073 * @throws IndexOutOfBoundsException if the start index is out of bounds 074 */ 075 public ArrayListIterator(final Object array, final int startIndex) { 076 super(array, startIndex); 077 } 078 079 /** 080 * Constructs an ArrayListIterator that will iterate over a range of values 081 * in the specified array. 082 * 083 * @param array the array to iterate over 084 * @param startIndex the index to start iterating at 085 * @param endIndex the index (exclusive) to finish iterating at 086 * @throws IllegalArgumentException if {@code array} is not an array. 087 * @throws IndexOutOfBoundsException if the start or end index is out of bounds 088 * @throws IllegalArgumentException if end index is before the start 089 * @throws NullPointerException if {@code array} is {@code null} 090 */ 091 public ArrayListIterator(final Object array, final int startIndex, final int endIndex) { 092 super(array, startIndex, endIndex); 093 } 094 095 /** 096 * This iterator does not support modification of its backing collection, and so will 097 * always throw an {@link UnsupportedOperationException} when this method is invoked. 098 * 099 * @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 /** 109 * Returns true if there are previous elements to return from the array. 110 * 111 * @return true if there is a previous element to return 112 */ 113 @Override 114 public boolean hasPrevious() { 115 return index > startIndex; 116 } 117 118 /** 119 * Gets the next element from the array. 120 * 121 * @return the next element 122 * @throws NoSuchElementException if there is no next element 123 */ 124 @Override 125 @SuppressWarnings("unchecked") 126 public E next() { 127 if (!hasNext()) { 128 throw new NoSuchElementException(); 129 } 130 lastItemIndex = index; 131 return (E) Array.get(array, index++); 132 } 133 134 /** 135 * Gets the next index to be retrieved. 136 * 137 * @return the index of the item to be retrieved next 138 */ 139 @Override 140 public int nextIndex() { 141 return index - startIndex; 142 } 143 144 /** 145 * Gets the previous element from the array. 146 * 147 * @return the previous element 148 * @throws NoSuchElementException if there is no previous element 149 */ 150 @Override 151 @SuppressWarnings("unchecked") 152 public E previous() { 153 if (!hasPrevious()) { 154 throw new NoSuchElementException(); 155 } 156 lastItemIndex = --index; 157 return (E) Array.get(array, index); 158 } 159 160 /** 161 * Gets the index of the item to be retrieved if {@link #previous()} is called. 162 * 163 * @return the index of the item to be retrieved next 164 */ 165 @Override 166 public int previousIndex() { 167 return index - startIndex - 1; 168 } 169 170 /** 171 * Resets the iterator back to the start index. 172 */ 173 @Override 174 public void reset() { 175 super.reset(); 176 lastItemIndex = -1; 177 } 178 179 /** 180 * Sets the element under the cursor. 181 * <p> 182 * This method sets the element that was returned by the last call 183 * to {@link #next()} of {@link #previous()}. 184 * </p> 185 * <p> 186 * <strong>Note:</strong> {@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 * </p> 193 * 194 * @param o the element to set 195 * @throws IllegalStateException if {@link #next()} or {@link #previous()} has not been called 196 * before {@link #set(Object)} 197 * @see java.util.ListIterator#set 198 */ 199 @Override 200 public void set(final Object o) { 201 if (lastItemIndex == -1) { 202 throw new IllegalStateException("must call next() or previous() before a call to set()"); 203 } 204 205 Array.set(array, lastItemIndex, o); 206 } 207 208}