What is a simple and fast way to get an iterator that returns at most N elements from the start of a List
?
The simplest versions I could come up with are:
#1:
import com.google.common.collect.Iterators;
// ...
public static <E> Iterator<E> lengthLimitedIterator(Iterable<E> source, int maxLen) {
return Iterators.partition(source.iterator(), maxLen).next().iterator();
}
#2:
public static <E> Iterator<E> lengthLimitedIterator(List<E> source, int maxLen) {
return source.subList(0, Math.min(source.size(), maxLen)).iterator();
}
Unfortunately both versions create a temporary List
which significantly affects performance as I am calling this method millions of times in a tight loop.
Are there any other library functions I could use for this?
Note: I cannot avoid iterating over the list as I am passing it to a method which takes an iterator as its argument and I cannot modify that class.
You already know it's a list, so you can just call the List.subList(int fromIndex, int toIndex)
method. As per the specification, the subList is backed by the original list, so it's not really creating a full blown List
, just some kind of proxy object.
Why not simply
list.subList(0, 42).iterator();
I am not sure why you mind about the creation of that temporary list. It doesn't do anything I'd consider expensive. In fact, creating this list is by far cheaper than iterating over it, which I assume you do.
Seems as if the feature will be added to guava, currently (as of r06) in beta:
public static <T> Iterator<T> limit(Iterator<T> iterator, int limitSize)
This is a place where a Decorator works very well: your decorator keeps a count, which is incremented by next()
, and used by control hasNext()
.
Example (intentionally incomplete):
public class LengthLimitedIterator<T>
implements Iterator<T>
{
private Iterator<T> _wrapped;
private int _length;
private int _count;
public LengthLimitedIterator(Iterator<T> wrapped, int length)
{
_wrapped = wrapped;
_length = length;
}
public boolean hasNext()
{
if (_count < _length)
return _wrapped.hasNext();
return false;
}
public T next()
{
// FIXME - add exception if count >= length
_count++;
return _wrapped.next();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With