![JAR search and dependency download from the Maven repository](/logo.png)
org.jhotdraw8.icollection.impl.champ.ChampIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.jhotdraw8.icollection Show documentation
Show all versions of org.jhotdraw8.icollection Show documentation
JHotDraw8 Immutable Collections
The newest version!
package org.jhotdraw8.icollection.impl.champ;
import org.jspecify.annotations.Nullable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Function;
/**
* CHAMP Trie iterator.
*
* References:
*
* This class has been derived from 'The Capsule Hash Trie Collections Library'.
*
* - The Capsule Hash Trie Collections Library.
*
Copyright (c) Michael Steindorfer. BSD-2-Clause License
* - github.com
*
*
*
* @param the data type of the trie node
* @param the element type of the iterator
*/
public class ChampIterator implements Iterator {
private final Function mappingFunction;
private static final int MAX_DEPTH = 7;
protected int currentValueCursor;
protected int currentValueLength;
protected Node currentValueNode;
private int currentStackLevel = -1;
private final int[] indexAndArity = new int[MAX_DEPTH * 2];
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
final Node[] nodes = new Node[MAX_DEPTH];
@SuppressWarnings("unchecked")
public ChampIterator(Node rootNode, @Nullable Function mappingFunction) {
this.mappingFunction = mappingFunction == null ? k -> (E) k : mappingFunction;
if (rootNode.hasNodes()) {
currentStackLevel = 0;
nodes[0] = rootNode;
indexAndArity[0] = 0;
indexAndArity[1] = rootNode.nodeArity();
}
if (rootNode.hasData()) {
currentValueNode = rootNode;
currentValueCursor = 0;
currentValueLength = rootNode.dataArity();
}
}
/*
* search for next node that contains values
*/
private boolean searchNextValueNode() {
// For inlining, it is essential that this method has a very small amount of byte code!
while (currentStackLevel >= 0) {
var index = currentStackLevel << 1;
if (indexAndArity[index] < indexAndArity[index + 1]) {
var nextNode = nodes[currentStackLevel].getNode(indexAndArity[index]);
indexAndArity[index]++;
if (nextNode.hasNodes()) {
// put node on next stack level for depth-first traversal
++currentStackLevel;
index += 2;
nodes[currentStackLevel] = nextNode;
indexAndArity[index] = 0;
indexAndArity[index + 1] = nextNode.nodeArity();
}
if (nextNode.hasData()) {
// found next node that contains values
currentValueNode = nextNode;
currentValueCursor = 0;
currentValueLength = nextNode.dataArity();
return true;
}
} else {
currentStackLevel--;
}
}
return false;
}
public boolean hasNext() {
// For inlining, it is essential that this method has a very small amount of byte code!
// Specifically, do not inline searchNextValueNode() into this method!
return currentValueCursor < currentValueLength || searchNextValueNode();
}
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
} else {
return mappingFunction.apply(currentValueNode.getData(currentValueCursor++));
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy