summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorBen Culkin <scorpress@gmail.com>2020-10-06 20:12:14 -0400
committerBen Culkin <scorpress@gmail.com>2020-10-06 20:12:14 -0400
commit3460b2c0c571a61068f664adc5a1b97f6a24cdcc (patch)
treee0cf4c80983a71bf0effac045044ab508877ca90 /src/main
parentf3ecbf3ed7d496ad7652a081fcafa494846b2878 (diff)
Add ResettableIterator
Adds ResettableIterator, an iterator type which caches the elements it iterates over, so as to allow you to re-iterate over them at your leisure. Note that because this works by caching, it can consume large amounts of memory if used on large iterators. In general, I would suggest only using this on medium-sized or smaller iterators you know you want to re-iterate over.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/bjc/data/ResettableIterator.java106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/main/java/bjc/data/ResettableIterator.java b/src/main/java/bjc/data/ResettableIterator.java
new file mode 100644
index 0000000..2208fb2
--- /dev/null
+++ b/src/main/java/bjc/data/ResettableIterator.java
@@ -0,0 +1,106 @@
+package bjc.data;
+
+import java.util.*;
+
+/*
+ * @TODO Oct 6, 2020 - Ben Culkin - :CleverCache
+ *
+ * In the future, there are certain efficencies we could take with our cached
+ * elements; namely, the case where we repeat the same element multiple times,
+ * or the case where we have a mixture of identical (and probably sizable) elements
+ *
+ * The general downside to these of course, is that these efficencies would cost
+ * us something in terms of complexity, as well as not benefitting iterators which
+ * aren't large enough.
+ *
+ * Still an interesting thought as to the best way to implement such a thing though.
+ */
+
+/**
+ * An iterator which can go back to the beginning of its iteration sequence at
+ * any point.
+ *
+ * @author Ben Culkin
+ *
+ * @param <T>
+ * The type iterated over.
+ */
+public class ResettableIterator<T> implements Iterator<T> {
+ private List<T> cache;
+ private Iterator<T> backing;
+
+ private boolean isRepeating = false;
+ private Iterator<T> cacheIterator;
+
+ /**
+ * Create a new resettable iterator.
+ *
+ * @param itr
+ * The iterator to iterate over.
+ */
+ public ResettableIterator(Iterator<T> itr) {
+ backing = itr;
+
+ cache = new ArrayList<>();
+ }
+
+ /**
+ * Create a new resettable iterator.
+ *
+ * @param itr
+ * The iterable to iterate over.
+ */
+ public ResettableIterator(Iterable<T> itr) {
+ this(itr.iterator());
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (isRepeating) {
+ return cacheIterator.hasNext() ? true : backing.hasNext();
+ } else {
+ return backing.hasNext();
+ }
+ }
+
+ @Override
+ public T next() {
+ if (isRepeating) {
+ if (cacheIterator.hasNext()) {
+ return cacheIterator.next();
+ } else {
+ cacheIterator = null;
+ isRepeating = false;
+ }
+ }
+
+ T itm = backing.next();
+
+ cache.add(itm);
+
+ return itm;
+ }
+
+ /**
+ * Reset this iterator to its starting point.
+ */
+ public void reset() {
+ isRepeating = true;
+
+ cacheIterator = cache.iterator();
+ }
+
+ /**
+ * Clears the cache of items.
+ *
+ * This will immediately return the iterator to the last actual item from the
+ * sequence, as well as making that the first item to be iterated over in the
+ * future.
+ */
+ public void clearCache() {
+ isRepeating = false;
+ cacheIterator = null;
+
+ cache = new ArrayList<>();
+ }
+}