blob: 26a0a993d8c2ce70362446a1a287dd4e73fb8622 [file] [log] [blame]
/*
* 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.jena.util.iterator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
Creates a sub-Iterator by filtering. This class should not be used
directly any more; the subclasses FilterKeepIterator and FilterDropIterator
should be used instead.
*/
public class FilterIterator<T> extends WrappedIterator<T>
{
protected final Predicate<T> f;
protected T current;
protected boolean canRemove;
protected boolean hasCurrent;
/**
Initialises a FilterIterator with its filter and base.
@param fl An object is included if it is accepted by this Filter.
@param e The base Iterator.
*/
public FilterIterator( Predicate<T> fl, Iterator<T> e )
{
super( e );
f = fl;
}
/**
Answer true iff there is at least one more acceptable object.
[Stores reference into <code>current</code>, sets <code>canRemove</code>
false; answer preserved in `hasCurrent`]
*/
@Override public boolean hasNext()
{
while (!hasCurrent && super.hasNext())
hasCurrent = f.test( current = super.next() );
canRemove = false;
return hasCurrent;
}
/**
Remove the current member from the underlying iterator. Legal only
after a .next() but before any subsequent .hasNext(), because that
may advance the underlying iterator.
*/
@Override public void remove()
{
if (!canRemove ) throw new IllegalStateException
( "FilterIterators do not permit calls to hasNext between calls to next and remove." );
super.remove();
}
/**
Answer the next acceptable object from the base iterator. The redundant
test of `hasCurrent` appears to make a detectable speed difference.
Crazy.
*/
@Override public T next()
{
if (hasCurrent || hasNext())
{
canRemove = true;
hasCurrent = false;
return current;
}
throw new NoSuchElementException();
}
@Override
public void forEachRemaining(Consumer<? super T> action)
{
if (hasCurrent) {
action.accept(current);
hasCurrent = false;
}
super.forEachRemaining(e -> {
if (f.test(e)) {
action.accept(e);
}
});
}
}