![JAR search and dependency download from the Maven repository](/logo.png)
xdean.jex.extra.collection.Traverse Maven / Gradle / Ivy
The newest version!
package xdean.jex.extra.collection;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.function.Function;
import io.reactivex.Flowable;
import xdean.jex.extra.rx2.RxIterator;
public class Traverse {
@FunctionalInterface
public interface Traversable extends Iterable {
Flowable traverse(Traverser t);
default Traverser defaultTraverser() {
return DefaultTraverser.BREAD_FIRST;
}
@Override
default Iterator iterator() {
return iterator(defaultTraverser());
}
default Iterator iterator(Traverser traverser) {
return traverse(traverser).to(RxIterator.flowableIterator());
}
default Flowable preOrderTraversal() {
return traverse(DefaultTraverser.PRE_ORDER);
}
default Flowable postOrderTraversal() {
return traverse(DefaultTraverser.POST_ORDER);
}
default Flowable breadthFirstTraversal() {
return traverse(DefaultTraverser.BREAD_FIRST);
}
}
@FunctionalInterface
public interface Traverser {
Flowable travese(T root, Function> getChildren);
}
public enum DefaultTraverser implements Traverser {
PRE_ORDER(Traverse::preOrderTraversal),
POST_ORDER(Traverse::postOrderTraversal),
BREAD_FIRST(Traverse::breadthFirstTraversal);
private final Traverser traverser;
private DefaultTraverser(Traverser traverser) {
this.traverser = traverser;
}
@Override
public Flowable travese(T root, Function> getChildren) {
return traverser.travese(root, getChildren);
}
}
private static Deque newDeque(T root) {
Deque deque = new ArrayDeque<>();
deque.add(root);
return deque;
}
public static Flowable preOrderTraversal(T root, Function> getChildren) {
return Flowable.generate(() -> newDeque(Arrays.asList(root).iterator()), (d, e) -> {
Iterator iterator;
while (true) {
if (d.isEmpty()) {
e.onComplete();
return;
}
iterator = d.peek();
if (iterator.hasNext()) {
break;
} else {
d.pop();
}
}
T t = iterator.next();
e.onNext(t);
Iterator children = getChildren.apply(t).iterator();
if (children.hasNext()) {
d.push(children);
}
});
}
public static Flowable postOrderTraversal(T root, Function> getChildren) {
return Flowable.generate(() -> newDeque(Either., T> left(Arrays.asList(root).iterator())), (d, e) -> {
Either, T> item;
while (true) {
if (d.isEmpty()) {
e.onComplete();
return;
}
item = d.peek();
item.exec(iterator -> {
if (iterator.hasNext()) {
T t = iterator.next();
Iterator children = getChildren.apply(t).iterator();
d.push(Either.right(t));
if (children.hasNext()) {
d.push(Either.left(children));
}
} else {
d.pop();
}
}, value -> {
d.pop();
e.onNext(value);
});
if (item.isRight()) {
return;
}
}
});
}
public static Flowable breadthFirstTraversal(T root, Function> getChildren) {
return Flowable.generate(() -> newDeque(Arrays.asList(root).iterator()), (d, e) -> {
Iterator iterator;
while (true) {
if (d.isEmpty()) {
e.onComplete();
return;
}
iterator = d.peek();
if (iterator.hasNext()) {
break;
} else {
d.pop();
}
}
T t = iterator.next();
e.onNext(t);
Iterator children = getChildren.apply(t).iterator();
if (children.hasNext()) {
d.addLast(children);
}
});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy