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.functor.core.collection;
18
19 import java.util.Iterator;
20 import java.util.NoSuchElementException;
21
22 import org.apache.commons.functor.UnaryPredicate;
23
24 /**
25 * Iterator that filters another Iterator by only passing through those elements
26 * that are matched by a specified UnaryPredicate.
27 * @version $Revision: 1156789 $ $Date: 2011-08-11 22:05:09 +0200 (Thu, 11 Aug 2011) $
28 * @author Rodney Waldhoff
29 */
30 public final class FilteredIterator<T> implements Iterator<T> {
31 // attributes
32 // ------------------------------------------------------------------------
33
34 private final UnaryPredicate<? super T> predicate;
35 private final Iterator<? extends T> iterator;
36
37 private T next = null;
38 private boolean nextSet = false;
39 private boolean canRemove = false;
40
41 // constructor
42 // ------------------------------------------------------------------------
43 /**
44 * Create a new FilteredIterator.
45 * @param iterator to filter
46 * @param predicate to apply
47 */
48 public FilteredIterator(Iterator<? extends T> iterator, UnaryPredicate<? super T> predicate) {
49 if (null == iterator) {
50 throw new IllegalArgumentException("Iterator argument was null");
51 }
52 if (null == predicate) {
53 throw new IllegalArgumentException("filtering UnaryPredicate argument was null");
54 }
55 this.predicate = predicate;
56 this.iterator = iterator;
57 }
58
59 // iterator methods
60 // ------------------------------------------------------------------------
61
62 /**
63 * {@inheritDoc}
64 * @see java.util.Iterator#hasNext()
65 */
66 public boolean hasNext() {
67 return nextSet || setNext();
68 }
69
70 /**
71 * {@inheritDoc}
72 * @see java.util.Iterator#next()
73 */
74 public T next() {
75 if (hasNext()) {
76 return returnNext();
77 }
78 throw new NoSuchElementException();
79 }
80
81 /**
82 * {@inheritDoc}
83 * @see java.util.Iterator#remove()
84 */
85 public void remove() {
86 if (canRemove) {
87 canRemove = false;
88 iterator.remove();
89 } else {
90 throw new IllegalStateException();
91 }
92 }
93
94 /**
95 * {@inheritDoc}
96 */
97 public boolean equals(Object obj) {
98 if (obj == this) {
99 return true;
100 }
101 if (!(obj instanceof FilteredIterator<?>)) {
102 return false;
103 }
104 FilteredIterator<?> that = (FilteredIterator<?>) obj;
105 return predicate.equals(that.predicate) && iterator.equals(that.iterator);
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 public int hashCode() {
112 int hash = "FilteredIterator".hashCode();
113 hash <<= 2;
114 hash ^= predicate.hashCode();
115 hash <<= 2;
116 hash ^= iterator.hashCode();
117 return hash;
118 }
119
120 /**
121 * {@inheritDoc}
122 */
123 public String toString() {
124 return "FilteredIterator<" + iterator + "," + predicate + ">";
125 }
126
127 // static methods
128 // ------------------------------------------------------------------------
129 /**
130 * Get a filtered Iterator instance applying <code>pred</code> to <code>iter</code>.
131 * @param iter to filter
132 * @param pred to apply
133 * @return Iterator
134 */
135 @SuppressWarnings("unchecked")
136 public static <T> Iterator<T> filter(Iterator<? extends T> iter, UnaryPredicate<? super T> pred) {
137 return null == pred ? (Iterator<T>) iter : (null == iter ? null : new FilteredIterator<T>(iter, pred));
138 }
139
140 // private
141 // ------------------------------------------------------------------------
142 /**
143 * Set next element.
144 * @return whether the current iterator position is valid
145 */
146 private boolean setNext() {
147 while (iterator.hasNext()) {
148 canRemove = false;
149 T obj = iterator.next();
150 if (predicate.test(obj)) {
151 nextSet = true;
152 next = obj;
153 return true;
154 }
155 }
156 next = null;
157 nextSet = false;
158 return false;
159 }
160
161 /**
162 * Get the next element.
163 * @return next element.
164 */
165 private T returnNext() {
166 T temp = next;
167 canRemove = true;
168 next = null;
169 nextSet = false;
170 return temp;
171 }
172
173 }