import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

class Scratch {

    public static void main(String[] args) {
        Node<Integer> root = new Node<>(8, List.of(
                new Node<>(4, List.of(
                        new Node<>(1),
                        new Node<>(4),
                        new Node<>(3))),
                new Node<>(3, List.of(
                        new Node<>(3),
                        new Node<>(5),
                        new Node<>(6),
                        new Node<>(4))),
                new Node<>(7, List.of(
                        new Node<>(12),
                        new Node<>(32),
                        new Node<>(3),
                        new Node<>(1)))));
        System.out.println(getMaxValuePerLevel(root));
    }

    public static <T extends Comparable<T>> List<T> getMaxValuePerLevel(Node<T> node) {
        final ArrayList<T> maxPerLevel = new ArrayList<>();
        maxPerLevel.add(node.getValue());
        List<Node<T>> children = node.getChildren();
        while (!children.isEmpty()) {
            final Node<T> defaultNode = children.get(0);
            maxPerLevel.add(children.stream()
                    .map(Node::getValue)
                    .max(Comparator.naturalOrder())
                    .orElseGet(defaultNode::getValue));
            children = children.stream()
                    .map(Node::getChildren)
                    .flatMap(List::stream)
                    .collect(Collectors.toList());
        }
        return maxPerLevel;
    }
}

class Node<T extends Comparable<T>> {
    private final T value;
    private final List<Node<T>> children;

    public Node(T value) {
        this(value, Collections.emptyList());
    }

    public Node(T value, List<Node<T>> children) {
        this.value = Objects.requireNonNull(value);
        this.children = Objects.requireNonNull(children).stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toUnmodifiableList());
    }

    public T getValue() {
        return value;
    }

    public List<Node<T>> getChildren() {
        return children;
    }
}