![JAR search and dependency download from the Maven repository](/logo.png)
org.dmfs.iterables.CachingIterable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of iterators Show documentation
Show all versions of iterators Show documentation
A collection of Iterator implementations.
/*
* Copyright (C) 2016 Marten Gajda
*
*
* Licensed 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.dmfs.iterables;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* An {@link Iterable} that stores the result of a given {@link Iterator} and allows to re-iterate the values. This is meant to speed up repeated access to slow
* iterators.
*
* Note that {@link CachingIterable} needs to synchronize access to the original iterator (and an internal list), which causes some overhead. So only use this
* if reiterating the original source is impossible or expensive (compared to the number of times you need to reiterate).
*
* @author Marten Gajda
*
* @param
* The type of the iterated elements.
*/
public final class CachingIterable implements Iterable
{
private final List mCache;
private final Iterator mSourceIterator;
private boolean mComplete;
public CachingIterable(Iterator iterator)
{
mCache = new ArrayList(64);
mSourceIterator = iterator;
}
@Override
public Iterator iterator()
{
// check if we can skip to synchronize because we already know that the cache is populated
if (!mComplete)
{
synchronized (mSourceIterator)
{
if (mSourceIterator.hasNext())
{
// we're still in the process of populating the cache
return new SynchronizedCachingIterator(mSourceIterator, mCache, mCache.size());
}
// store that the iterator was completely iterated, so we don't need to check next time
mComplete = true;
}
}
// The cache is completely populated. That means we don't need the synchronized iterator anymore.
// Just return an iterator on the cache. Make sure the consumer can't modify our cache.
return Collections.unmodifiableList(mCache).iterator();
}
/**
* An iterator that stores all iterated values in a "cache" {@link List} for further reiteration.
*
* @author Marten Gajda
*
* @param
* The type of the iterated elements.
*/
private final static class SynchronizedCachingIterator implements Iterator
{
private final Iterator mOriginalIterator;
private final List mCache;
private final int mSafeElements;
private int mPos;
public SynchronizedCachingIterator(Iterator originalIterator, List cache, int safeElements)
{
mOriginalIterator = originalIterator;
mCache = cache;
mSafeElements = safeElements;
}
@Override
public boolean hasNext()
{
if (mPos < mSafeElements)
{
// we already know that there are this many elements in the cache, so no need to enter the expensive synchronized block
return true;
}
synchronized (mOriginalIterator)
{
// TODO: does it make sense to update mSafeElements in here?
return mPos < mCache.size() || mOriginalIterator.hasNext();
}
}
@Override
public T next()
{
synchronized (mOriginalIterator)
{
if (mPos == mCache.size())
{
// the list has no more elements, try to append one from the original iterator
T next = mOriginalIterator.next();
mCache.add(next);
mPos++;
return next;
}
// TODO: does it make sense to update mSafeElements in here?
// this needs to be synchronized as well since the add operation might leave the list in an invalid state for a short time (like during a
// resize of the backing array).
return mCache.get(mPos++);
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException("Remove is not supported by this Iterator.");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy