Is there a conventional iterator interface in Java which separates traversal from element access? -
for application, element access expensive, java.util.iterator no use. want more c++ iterators, can move pointer around without returning element. there in standard library this, or has de facto standard interface evolved through custom? (if not, please don't waste time posting code snippets - i'm quite able think reasonable names job).
(since no 1 came around write proper answer, i'll expand comments answer.)
to extent of knowledge there's no interface in standard api suits (i.e. interface iterator.skip()
). best solution using standard api methods believe, yourlist.sublist(startindex).iterator()
instance.
i think that, if possible, should consider creating own iterator interface. (note can let extend java.util.iterator
interface able use ordinary iterator if needed.)
finally, , future readers have use java.util.iterator
, have access underlying list lazily, can use java.lang.reflect.proxy
. note proxy
objects doesn't play serialization / persistence libraries, , requires work interfaces. example follows:
here's slow ondisklist
fetches line n in each call get(int n)
:
class ondisklist extends abstractlist<charsequence> { // slow list access method: linear search n:th line. @override public charsequence get(int n) { system.out.println("fetching line " + n + "..."); try (stream<string> lines = files.lines(paths.get("big-file.txt"))) { return lines.skip(n).findfirst().get(); } catch (ioexception shouldbehandled) { return null; } } @override public int size() { return 5; } }
here's how output looks when using ordinary iterator:
iterator<charsequence> normaliter = ondisklist.iterator(); normaliter.next(); // skip normaliter.next(); // skip normaliter.next(); // skip system.out.println(normaliter.next()); // print
output:
fetching line 0... fetching line 1... fetching line 2... fetching line 3... line 3 in big-file.txt
now magic: here's proxyingiterator
hides object behind proxy
accesses list lazily:
class proxyingiterator implements iterator<charsequence> { list<charsequence> slowlist; int pos = 0; public proxyingiterator(list<charsequence> slowlist) { this.slowlist = slowlist; } @override public boolean hasnext() { return pos < slowlist.size(); } @override public charsequence next() { return (charsequence) proxy.newproxyinstance( charsequence.class.getclassloader(), new class[] { charsequence.class }, new lazyloadinginvocationhandler(pos++)); } private class lazyloadinginvocationhandler implements invocationhandler { int index; charsequence loadedobject = null; public lazyloadinginvocationhandler(int index) { this.index = index; } @override public object invoke(object proxy, method method, object[] args) { if (loadedobject == null) loadedobject = slowlist.get(index); try { return method.invoke(loadedobject, args); } catch (exception shouldnothappen) { shouldnothappen.printstacktrace(); return null; } } } }
when using iterator looks follows:
iterator<charsequence> proxyingiter = new proxyingiterator(ondisklist); proxyingiter.next(); // skip proxyingiter.next(); // skip proxyingiter.next(); // skip system.out.println(proxyingiter.next()); // print
output:
fetching line 3... line 3 in big-file.txt
Comments
Post a Comment