in utils/src/main/java/jetbrains/exodus/core/dataStructures/persistent/AbstractPersistent23Tree.java [236:302]
public Iterator<K> reverseIterator() {
if (isEmpty()) {
return Collections.EMPTY_LIST.iterator();
}
final RootNode<K> root = getRoot();
final TreePosRev<K>[] stack = new TreePosRev[MathUtil.integerLogarithm(root.getSize()) + 1];
for (int i = 0; i < stack.length; ++i) {
stack[i] = new TreePosRev<>(root);
}
return new Iterator<K>() {
private int i = 0;
private boolean hasNext;
private boolean hasNextValid;
@Override
public boolean hasNext() {
if (hasNextValid) {
return hasNext;
}
hasNextValid = true;
TreePosRev<K> treePos = stack[i];
if (treePos.node.isLeaf()) {
while (treePos.pos <= 1) {
if (--i < 0) {
hasNext = false;
return false;
}
treePos = stack[i];
}
} else {
TreePosRev<K> newPos = stack[++i];
if (treePos.pos == 1) {
newPos.setNode(treePos.node.getFirstChild());
} else if (treePos.pos == 2) {
newPos.setNode(treePos.node.getSecondChild());
} else {
newPos.setNode(treePos.node.getThirdChild());
}
treePos = newPos;
while (!treePos.node.isLeaf()) {
newPos = stack[++i];
newPos.setNode(treePos.node.isTernary() ? treePos.node.getThirdChild() : treePos.node.getSecondChild());
treePos = newPos;
}
}
treePos.pos--;
return hasNext = true;
}
@Override
public K next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
hasNextValid = false;
final TreePosRev<K> treePos = stack[i];
// treePos.pos must be 1 or 2 here
return treePos.pos == 1 ? treePos.node.getFirstKey() : treePos.node.getSecondKey();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}