FilterListIterator.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.collections4.iterators;
- import java.util.ListIterator;
- import java.util.NoSuchElementException;
- import org.apache.commons.collections4.Predicate;
- /**
- * Decorates another {@link ListIterator} using a predicate to filter elements.
- * <p>
- * This iterator decorates the underlying iterator, only allowing through
- * those elements that match the specified {@link Predicate Predicate}.
- * </p>
- *
- * @param <E> the type of elements returned by this iterator.
- * @since 2.0
- */
- public class FilterListIterator<E> implements ListIterator<E> {
- /** The iterator being used */
- private ListIterator<? extends E> iterator;
- /** The predicate being used */
- private Predicate<? super E> predicate;
- /**
- * The value of the next (matching) object, when
- * {@link #nextObjectSet} is true.
- */
- private E nextObject;
- /**
- * Whether or not the {@link #nextObject} has been set
- * (possibly to {@code null}).
- */
- private boolean nextObjectSet;
- /**
- * The value of the previous (matching) object, when
- * {@link #previousObjectSet} is true.
- */
- private E previousObject;
- /**
- * Whether or not the {@link #previousObject} has been set
- * (possibly to {@code null}).
- */
- private boolean previousObjectSet;
- /**
- * The index of the element that would be returned by {@link #next}.
- */
- private int nextIndex;
- /**
- * Constructs a new {@code FilterListIterator} that will not function
- * until {@link #setListIterator(ListIterator) setListIterator}
- * and {@link #setPredicate(Predicate) setPredicate} are invoked.
- */
- public FilterListIterator() {
- }
- /**
- * Constructs a new {@code FilterListIterator} that will not
- * function until {@link #setPredicate(Predicate) setPredicate} is invoked.
- *
- * @param iterator the iterator to use
- */
- public FilterListIterator(final ListIterator<? extends E> iterator) {
- this.iterator = iterator;
- }
- /**
- * Constructs a new {@code FilterListIterator}.
- *
- * @param iterator the iterator to use
- * @param predicate the predicate to use
- */
- public FilterListIterator(final ListIterator<? extends E> iterator, final Predicate<? super E> predicate) {
- this.iterator = iterator;
- this.predicate = predicate;
- }
- /**
- * Constructs a new {@code FilterListIterator} that will not function
- * until {@link #setListIterator(ListIterator) setListIterator} is invoked.
- *
- * @param predicate the predicate to use.
- */
- public FilterListIterator(final Predicate<? super E> predicate) {
- this.predicate = predicate;
- }
- /**
- * Not supported.
- * @param o the element to insert
- */
- @Override
- public void add(final E o) {
- throw new UnsupportedOperationException("FilterListIterator.add(Object) is not supported.");
- }
- private void clearNextObject() {
- nextObject = null;
- nextObjectSet = false;
- }
- private void clearPreviousObject() {
- previousObject = null;
- previousObjectSet = false;
- }
- /**
- * Gets the iterator this iterator is using.
- *
- * @return the iterator.
- */
- public ListIterator<? extends E> getListIterator() {
- return iterator;
- }
- /**
- * Gets the predicate this iterator is using.
- *
- * @return the predicate.
- */
- public Predicate<? super E> getPredicate() {
- return predicate;
- }
- @Override
- public boolean hasNext() {
- return nextObjectSet || setNextObject();
- }
- @Override
- public boolean hasPrevious() {
- return previousObjectSet || setPreviousObject();
- }
- @Override
- public E next() {
- if (!nextObjectSet && !setNextObject()) {
- throw new NoSuchElementException();
- }
- nextIndex++;
- final E temp = nextObject;
- clearNextObject();
- return temp;
- }
- @Override
- public int nextIndex() {
- return nextIndex;
- }
- @Override
- public E previous() {
- if (!previousObjectSet && !setPreviousObject()) {
- throw new NoSuchElementException();
- }
- nextIndex--;
- final E temp = previousObject;
- clearPreviousObject();
- return temp;
- }
- @Override
- public int previousIndex() {
- return nextIndex - 1;
- }
- /** Not supported. */
- @Override
- public void remove() {
- throw new UnsupportedOperationException("FilterListIterator.remove() is not supported.");
- }
- /**
- * Not supported.
- * @param ignored the element with which to replace the last element returned by
- * {@code next} or {@code previous}
- */
- @Override
- public void set(final E ignored) {
- throw new UnsupportedOperationException("FilterListIterator.set(Object) is not supported.");
- }
- /**
- * Sets the iterator for this iterator to use.
- * If iteration has started, this effectively resets the iterator.
- *
- * @param iterator the iterator to use
- */
- public void setListIterator(final ListIterator<? extends E> iterator) {
- this.iterator = iterator;
- }
- private boolean setNextObject() {
- // if previousObjectSet,
- // then we've walked back one step in the
- // underlying list (due to a hasPrevious() call)
- // so skip ahead one matching object
- if (previousObjectSet) {
- clearPreviousObject();
- if (!setNextObject()) {
- return false;
- }
- clearNextObject();
- }
- if (iterator == null) {
- return false;
- }
- while (iterator.hasNext()) {
- final E object = iterator.next();
- if (predicate.test(object)) {
- nextObject = object;
- nextObjectSet = true;
- return true;
- }
- }
- return false;
- }
- /**
- * Sets the predicate this the iterator to use.
- *
- * @param predicate the transformer to use
- */
- public void setPredicate(final Predicate<? super E> predicate) {
- this.predicate = predicate;
- }
- private boolean setPreviousObject() {
- // if nextObjectSet,
- // then we've walked back one step in the
- // underlying list (due to a hasNext() call)
- // so skip ahead one matching object
- if (nextObjectSet) {
- clearNextObject();
- if (!setPreviousObject()) {
- return false;
- }
- clearPreviousObject();
- }
- if (iterator == null) {
- return false;
- }
- while (iterator.hasPrevious()) {
- final E object = iterator.previous();
- if (predicate.test(object)) {
- previousObject = object;
- previousObjectSet = true;
- return true;
- }
- }
- return false;
- }
- }