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 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 * 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 * 035 * @see org.apache.commons.collections4.iterators.ArrayIterator 036 * @see java.util.Iterator 037 * @see java.util.ListIterator 038 * 039 * @since 3.0 040 * @version $Id: ArrayListIterator.html 972421 2015-11-14 20:00:04Z tn $ 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()</code> 047 * or <code>previous()</code>. This is set to <code>-1</code> if neither method 048 * has yet been invoked. <code>lastItemIndex</code> is used to to implement 049 * the {@link #set} method. 050 */ 051 private int lastItemIndex = -1; 052 053 // Constructors 054 // ---------------------------------------------------------------------- 055 /** 056 * Constructs an ArrayListIterator that will iterate over the values in the 057 * specified array. 058 * 059 * @param array the array to iterate over 060 * @throws IllegalArgumentException if <code>array</code> is not an array. 061 * @throws NullPointerException if <code>array</code> is <code>null</code> 062 */ 063 public ArrayListIterator(final Object array) { 064 super(array); 065 } 066 067 /** 068 * Constructs an ArrayListIterator that will iterate over the values in the 069 * specified array from a specific start index. 070 * 071 * @param array the array to iterate over 072 * @param startIndex the index to start iterating at 073 * @throws IllegalArgumentException if <code>array</code> is not an array. 074 * @throws NullPointerException if <code>array</code> is <code>null</code> 075 * @throws IndexOutOfBoundsException if the start index is out of bounds 076 */ 077 public ArrayListIterator(final Object array, final int startIndex) { 078 super(array, startIndex); 079 } 080 081 /** 082 * Construct an ArrayListIterator that will iterate over a range of values 083 * in the specified array. 084 * 085 * @param array the array to iterate over 086 * @param startIndex the index to start iterating at 087 * @param endIndex the index (exclusive) to finish iterating at 088 * @throws IllegalArgumentException if <code>array</code> is not an array. 089 * @throws IndexOutOfBoundsException if the start or end index is out of bounds 090 * @throws IllegalArgumentException if end index is before the start 091 * @throws NullPointerException if <code>array</code> is <code>null</code> 092 */ 093 public ArrayListIterator(final Object array, final int startIndex, final int endIndex) { 094 super(array, startIndex, endIndex); 095 } 096 097 // ListIterator interface 098 //----------------------------------------------------------------------- 099 /** 100 * Returns true if there are previous elements to return from the array. 101 * 102 * @return true if there is a previous element to return 103 */ 104 public boolean hasPrevious() { 105 return this.index > this.startIndex; 106 } 107 108 /** 109 * Gets the previous element from the array. 110 * 111 * @return the previous element 112 * @throws NoSuchElementException if there is no previous element 113 */ 114 @SuppressWarnings("unchecked") 115 public E previous() { 116 if (hasPrevious() == false) { 117 throw new NoSuchElementException(); 118 } 119 this.lastItemIndex = --this.index; 120 return (E) Array.get(this.array, this.index); 121 } 122 123 /** 124 * Gets the next element from the array. 125 * 126 * @return the next element 127 * @throws NoSuchElementException if there is no next element 128 */ 129 @Override 130 @SuppressWarnings("unchecked") 131 public E next() { 132 if (hasNext() == false) { 133 throw new NoSuchElementException(); 134 } 135 this.lastItemIndex = this.index; 136 return (E) Array.get(this.array, this.index++); 137 } 138 139 /** 140 * Gets the next index to be retrieved. 141 * 142 * @return the index of the item to be retrieved next 143 */ 144 public int nextIndex() { 145 return this.index - this.startIndex; 146 } 147 148 /** 149 * Gets the index of the item to be retrieved if {@link #previous()} is called. 150 * 151 * @return the index of the item to be retrieved next 152 */ 153 public int previousIndex() { 154 return this.index - this.startIndex - 1; 155 } 156 157 /** 158 * This iterator does not support modification of its backing collection, and so will 159 * always throw an {@link UnsupportedOperationException} when this method is invoked. 160 * 161 * @param o the element to add 162 * @throws UnsupportedOperationException always thrown. 163 * @see java.util.ListIterator#set 164 */ 165 public void add(final Object o) { 166 throw new UnsupportedOperationException("add() method is not supported"); 167 } 168 169 /** 170 * Sets the element under the cursor. 171 * <p> 172 * This method sets the element that was returned by the last call 173 * to {@link #next()} of {@link #previous()}. 174 * <p> 175 * <b>Note:</b> {@link ListIterator} implementations that support 176 * <code>add()</code> and <code>remove()</code> only allow <code>set()</code> to be called 177 * once per call to <code>next()</code> or <code>previous</code> (see the {@link ListIterator} 178 * javadoc for more details). Since this implementation does 179 * not support <code>add()</code> or <code>remove()</code>, <code>set()</code> may be 180 * called as often as desired. 181 * 182 * @param o the element to set 183 * @throws IllegalStateException if {@link #next()} or {@link #previous()} has not been called 184 * before {@link #set(Object)} 185 * @see java.util.ListIterator#set 186 */ 187 public void set(final Object o) { 188 if (this.lastItemIndex == -1) { 189 throw new IllegalStateException("must call next() or previous() before a call to set()"); 190 } 191 192 Array.set(this.array, this.lastItemIndex, o); 193 } 194 195 /** 196 * Resets the iterator back to the start index. 197 */ 198 @Override 199 public void reset() { 200 super.reset(); 201 this.lastItemIndex = -1; 202 } 203 204}