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.functor.core.collection; 018 019import java.util.Iterator; 020import java.util.NoSuchElementException; 021 022import org.apache.commons.functor.Predicate; 023import org.apache.commons.lang3.Validate; 024 025/** 026 * Iterator that filters another Iterator by only passing through those elements 027 * that are matched by a specified Predicate. 028 * 029 * @param <T> the {@link Iterator} generic type 030 * @version $Revision: 1508677 $ $Date: 2013-07-31 00:48:02 +0200 (Mi, 31 Jul 2013) $ 031 */ 032public final class FilteredIterator<T> implements Iterator<T> { 033 // attributes 034 // ------------------------------------------------------------------------ 035 036 /** 037 * The predicate used to test this Iterator elements. 038 */ 039 private final Predicate<? super T> predicate; 040 /** 041 * The wrapped iterator. 042 */ 043 private final Iterator<? extends T> iterator; 044 045 /** 046 * Reference to next element has to be returned by this iterator. 047 */ 048 private T next = null; 049 /** 050 * Flag to mark this iterator has more elements or not. 051 */ 052 private boolean nextSet = false; 053 /** 054 * Flag to mark current iterator element can be removed. 055 */ 056 private boolean canRemove = false; 057 058 // constructor 059 // ------------------------------------------------------------------------ 060 /** 061 * Create a new FilteredIterator. 062 * @param iterator to filter 063 * @param predicate to apply 064 */ 065 public FilteredIterator(Iterator<? extends T> iterator, Predicate<? super T> predicate) { 066 this.iterator = Validate.notNull(iterator, "Iterator argument was null"); 067 this.predicate = Validate.notNull(predicate, "filtering Predicate argument was null"); 068 } 069 070 // iterator methods 071 // ------------------------------------------------------------------------ 072 073 /** 074 * {@inheritDoc} 075 * @see java.util.Iterator#hasNext() 076 */ 077 public boolean hasNext() { 078 return nextSet || setNext(); 079 } 080 081 /** 082 * {@inheritDoc} 083 * @see java.util.Iterator#next() 084 */ 085 public T next() { 086 if (hasNext()) { 087 return returnNext(); 088 } 089 throw new NoSuchElementException(); 090 } 091 092 /** 093 * {@inheritDoc} 094 * @see java.util.Iterator#remove() 095 */ 096 public void remove() { 097 if (canRemove) { 098 canRemove = false; 099 iterator.remove(); 100 } else { 101 throw new IllegalStateException(); 102 } 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public boolean equals(Object obj) { 110 if (obj == this) { 111 return true; 112 } 113 if (!(obj instanceof FilteredIterator<?>)) { 114 return false; 115 } 116 FilteredIterator<?> that = (FilteredIterator<?>) obj; 117 return predicate.equals(that.predicate) && iterator.equals(that.iterator); 118 } 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override 124 public int hashCode() { 125 int hash = "FilteredIterator".hashCode(); 126 hash <<= 2; 127 hash ^= predicate.hashCode(); 128 hash <<= 2; 129 hash ^= iterator.hashCode(); 130 return hash; 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 @Override 137 public String toString() { 138 return "FilteredIterator<" + iterator + "," + predicate + ">"; 139 } 140 141 // static methods 142 // ------------------------------------------------------------------------ 143 /** 144 * Get a filtered Iterator instance applying <code>pred</code> to <code>iter</code>. 145 * @param <T> the input iterator generic type 146 * @param iter to filter 147 * @param pred to apply 148 * @return Iterator 149 */ 150 @SuppressWarnings("unchecked") 151 public static <T> Iterator<T> filter(Iterator<? extends T> iter, Predicate<? super T> pred) { 152 return null == pred ? (Iterator<T>) iter : (null == iter ? null : new FilteredIterator<T>(iter, pred)); 153 } 154 155 // private 156 // ------------------------------------------------------------------------ 157 /** 158 * Set next element. 159 * @return whether the current iterator position is valid 160 */ 161 private boolean setNext() { 162 while (iterator.hasNext()) { 163 canRemove = false; 164 T obj = iterator.next(); 165 if (predicate.test(obj)) { 166 nextSet = true; 167 next = obj; 168 return true; 169 } 170 } 171 next = null; 172 nextSet = false; 173 return false; 174 } 175 176 /** 177 * Get the next element. 178 * @return next element. 179 */ 180 private T returnNext() { 181 T temp = next; 182 canRemove = true; 183 next = null; 184 nextSet = false; 185 return temp; 186 } 187 188}