缓存流迭代器PeekIterator是词法分析器的基础。我们是将源代码转换成“Stream流”来处理的,通过这个迭代器,就可以对代码的流进行一系列的操作了,包括正则校验、类型判断等。换句话说,这个迭代器就是把代码包含的字符一个一个地取出来,然后进行观察并操作。
peek和next函数默认先从栈顶取值,如果栈中无元素,再从流的下一个位置取元素,并将该元素放到队列尾。
代码如下,内含详细注释:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.stream.Stream;
/**
* @description : 需要一个队列和一个栈配合操作,putBack是从队列尾拿出元素,放入栈顶,而next是从
* 栈顶取出元素,再依次放回队列尾。
* @date : 2024-05-03 17:24
*/
public class PeekIterator<T> implements Iterator<T> {
// 队列
private LinkedList<T> queueCache = new LinkedList<>();
// 栈
private LinkedList<T> stackPutBacks = new LinkedList<>();
private Iterator<T> it;
private final static int CACHE_SIZE = 10;
private T _endToken = null;
public PeekIterator(Stream<T> stream) {
it = stream.iterator();
}
public PeekIterator(Stream<T> stream, T endToken) {
it = stream.iterator();
_endToken = endToken;
}
/**
* 与next不同之处在于,多次执行next函数,会将流中的元素依次取出来,这会改变取元素的位置。
* 而peek方法执行后,只会获取当前位置的下一位置的元素,并且不改变取元素的位置。
* 可以一直拿到同一个数据节点。
*/
public T peek() {
if (this.stackPutBacks.size() > 0) {
// 获取栈顶第一个元素
return this.stackPutBacks.getFirst();
}
if (!it.hasNext()) {
return _endToken;
}
T val = next();
// 取完下一个元素,就放入栈中,因此下次再执行peek方法,则从栈顶取值,依然返回相同的结果。
this.putBack();
return val;
}
/**
* putBack执行压栈操作,
* 有了putBack,就可以做到调用了多次next后,还可以取到之前数据,
* 相当于按了ctrl+v的回退操作,
* 期间产生的所有元素都放在stackPutBacks中,但是回退的次数不能超过CACHE_SIZE。
*/
public void putBack() {
if (this.queueCache.size() > 0) {
// stackPutBacks是栈,push方法实现先压栈,pop方法实现先进后出
this.stackPutBacks.push(this.queueCache.pollLast());
}
}
/**
* next方法取出流中的下一个元素。
*/
@Override
public T next() {
T val = null;
if (this.stackPutBacks.size() > 0) {
// putBack方法是:从队列尾拿出元素,放入栈顶。
// 而这里是从栈顶取出,下面再add进队列末尾。相当于恢复了队列中的数据。
val = this.stackPutBacks.pop();
} else {
if (!it.hasNext()) {
T tmp = _endToken;
_endToken = null;
return tmp;
}
val = it.next();
}
// 处理缓存
while (queueCache.size() > CACHE_SIZE - 1) {
queueCache.poll();
}
// queueCache是队列,poll方法实现先进先出
queueCache.add(val);
return val;
}
@Override
public boolean hasNext() {
return _endToken != null || this.stackPutBacks.size() > 0 || it.hasNext();
}
}