Skip to content

Instantly share code, notes, and snippets.

@yuba
Last active January 4, 2016 21:39
Show Gist options
  • Save yuba/8682001 to your computer and use it in GitHub Desktop.
Save yuba/8682001 to your computer and use it in GitHub Desktop.
CachedIterable<T>
package net.miuras;
import com.sun.istack.internal.NotNull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Even if you iterate a CachedIterable object several times, the source Iterable object will be iterated only once.
*
* It's thread-safe.
*/
public class CachedIterable<T> implements Iterable<T> {
@NotNull private Iterator<T> source;
private volatile int sourceSizeIsLargerThanOrEqualTo = 0;
@NotNull private ArrayList<T> cache = new ArrayList<T>();
@NotNull private Object monitor = new Object();
public CachedIterable(Iterable<T> source) throws IllegalArgumentException {
if (source == null) throw new IllegalArgumentException();
this.source = source.iterator();
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
int cachePointer = 0;
@Override
public boolean hasNext() {
synchronized(monitor) {
if (cachePointer < cache.size() || cachePointer < sourceSizeIsLargerThanOrEqualTo) return true;
final boolean sourceHasNext = source.hasNext();
if (sourceHasNext) sourceSizeIsLargerThanOrEqualTo = cache.size() + 1;
return sourceHasNext;
}
}
@Override
public T next() throws NoSuchElementException {
synchronized(monitor) {
if (cachePointer < cache.size()) return cache.get(cachePointer++);
T newElement = source.next(); // NoSuchElementException may be thrown here.
cache.add(newElement);
cachePointer++;
return newElement;
}
}
@Override
public void remove() throws UnsupportedOperationException{
throw new UnsupportedOperationException();
}
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment