summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/data/ResettableIterator.java
blob: 8c1c4aa7416e340b255c89cbfe865b480b674d6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package bjc.data;

import java.util.*;

/*
 * @TODO Oct 6, 2020 - Ben Culkin - :CleverCache
 * 
 * In the future, there are certain efficiencies 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 efficiencies would cost
 *  us something in terms of complexity, as well as not benefiting 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();
		return backing.hasNext();
	}

	@Override
	public T next() {
		if (isRepeating) {
			if (cacheIterator.hasNext()) {
				return cacheIterator.next();
			}
			
			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<>();
	}
}