1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.collections15.iterators;
17
18 import java.util.Iterator;
19 import java.util.NoSuchElementException;
20
21 import net.sf.collections15.Predicate;
22
23 /***
24 * Decorates an <code>Iterator</code> such that only elements matching a
25 * predicate filter are returned.
26 *
27 * @since Commons Collections 1.0
28 * @version $Revision: 1.1 $ $Date: 2005/02/27 19:33:42 $
29 *
30 * @author James Strachan
31 * @author Jan Sorensen
32 * @author Ralph Wagner
33 * @author Stephen Colebourne
34 * @author Mauro Franceschini (port to 5.0)
35 */
36 public class FilterIterator<E> implements Iterator<E> {
37
38
39
40
41 /*** The iterator being used */
42 private Iterator<E> iterator;
43
44 /*** The predicate being used */
45 private Predicate<E> predicate;
46
47 /*** The next object in the iteration */
48 private E nextObject;
49
50 /*** Whether the next object has been calculated yet */
51 private boolean nextObjectSet = false;
52
53
54
55
56 /***
57 * Constructs a new <code>FilterIterator</code> that will not function
58 * until {@link #setIterator(Iterator) setIterator} and
59 * {@link #setPredicate(Predicate) setPredicate} are invoked.
60 */
61 public FilterIterator() {
62 super();
63 }
64
65 /***
66 * Constructs a new <code>FilterIterator</code> that will not function
67 * until {@link #setPredicate(Predicate) setPredicate} is invoked.
68 *
69 * @param iterator the iterator to use
70 */
71 public FilterIterator(Iterator<E> iterator) {
72 super();
73 this.iterator = iterator;
74 }
75
76 /***
77 * Constructs a new <code>FilterIterator</code> that will use the
78 * given iterator and predicate.
79 *
80 * @param iterator the iterator to use
81 * @param predicate the predicate to use
82 */
83 public FilterIterator(Iterator<E> iterator, Predicate<E> predicate) {
84 super();
85 this.iterator = iterator;
86 this.predicate = predicate;
87 }
88
89
90
91
92 /***
93 * Returns <code>true</code> if the underlying iterator contains an object
94 * that matches the predicate.
95 *
96 * @return <code>true</code> if there is another object that matches the
97 * predicate
98 */
99 public boolean hasNext() {
100 if (nextObjectSet) {
101 return true;
102 } else {
103 return setNextObject();
104 }
105 }
106
107 /***
108 * Returns the next object that matches the predicate.
109 *
110 * @return the next object which matches the given predicate
111 *
112 * @throws NoSuchElementException if there are no more elements that match
113 * the predicate
114 */
115 public E next() {
116 if (!nextObjectSet) {
117 if (!setNextObject()) {
118 throw new NoSuchElementException();
119 }
120 }
121 nextObjectSet = false;
122 return nextObject;
123 }
124
125 /***
126 * Removes from the underlying collection of the base iterator the last
127 * element returned by this iterator.
128 * <p>
129 * This method can only be called if <code>next()</code> was called, but not
130 * after <code>hasNext()</code>, because the <code>hasNext()</code> call
131 * changes the base iterator.
132 *
133 * @throws IllegalStateException if <code>hasNext()</code> has already
134 * been called.
135 */
136 public void remove() {
137 if (nextObjectSet) {
138 throw new IllegalStateException("remove() cannot be called");
139 }
140 iterator.remove();
141 }
142
143
144
145
146 /***
147 * Gets the iterator this iterator is using.
148 *
149 * @return the iterator.
150 */
151 public Iterator<E> getIterator() {
152 return iterator;
153 }
154
155 /***
156 * Sets the iterator for this iterator to use.
157 * <p>
158 * If iteration has started, this effectively resets the iterator.
159 *
160 * @param iterator the iterator to use
161 */
162 public void setIterator(Iterator<E> iterator) {
163 this.iterator = iterator;
164 }
165
166 /***
167 * Gets the predicate this iterator is using.
168 *
169 * @return the predicate.
170 */
171 public Predicate<E> getPredicate() {
172 return predicate;
173 }
174
175 /***
176 * Sets the predicate this the iterator to use.
177 *
178 * @param predicate the predicate to use
179 */
180 public void setPredicate(Predicate<E> predicate) {
181 this.predicate = predicate;
182 }
183
184
185
186
187 /***
188 * Set nextObject to the next object.
189 *
190 * @return <code>false</code> if there are no more objects and
191 * <code>true</code> otherwise
192 */
193 private boolean setNextObject() {
194 while (iterator.hasNext()) {
195 E object = iterator.next();
196 if (predicate.evaluate(object)) {
197 nextObject = object;
198 nextObjectSet = true;
199 return true;
200 }
201 }
202 return false;
203 }
204 }