@Override default <U> Tree<Tuple2<T, U>> zipAll(Iterable<U> that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); if (isEmpty()) { return Iterator.ofAll(that).map(elem -> Tuple.of(thisElem, elem)).toTree(); } else { final java.util.Iterator<U> thatIter = that.iterator(); final Tree<Tuple2<T, U>> tree = ZipAll.apply((Node<T>) this, thatIter, thatElem); if (thatIter.hasNext()) { final Iterable<Node<Tuple2<T, U>>> remainder = Iterator.ofAll(thatIter).map(elem -> Tree.of(Tuple.of(thisElem, elem))); return new Node<>(tree.getValue(), tree.getChildren().appendAll(remainder)); } else { return tree; } } }
@SuppressWarnings("unchecked") static <T, U> Tree<U> apply( Node<T> node, Function<? super T, ? extends Iterable<? extends U>> mapper) { final Tree<U> mapped = Tree.ofAll(mapper.apply(node.getValue())); if (mapped.isEmpty()) { return Tree.empty(); } else { final List<Node<U>> children = (List<Node<U>>) (Object) node.getChildren() .map(child -> FlatMap.apply(child, mapper)) .filter(Tree::isDefined); return Tree.of(mapped.getValue(), children.prependAll(mapped.getChildren())); } }