@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<Tuple2<T, U>> apply(Node<T> node, java.util.Iterator<U> that, U thatElem) { if (!that.hasNext()) { return node.map(value -> Tuple.of(value, thatElem)); } else { final Tuple2<T, U> value = Tuple.of(node.getValue(), that.next()); final List<Node<Tuple2<T, U>>> children = (List<Node<Tuple2<T, U>>>) (Object) node.getChildren() .map(child -> ZipAll.apply(child, that, thatElem)) .filter(Tree::isDefined); return new Node<>(value, children); } }