public StrictBounds<OrderedElement<T>> findNewBound(Iterable<T> stream, long kOrder, Bounds<OrderedElement<T>> oldBounds) {
        ArrayList<OrderedElement<T>> current = new ArrayList<>(levelSize);
        List<ArrayList<OrderedElement<T>>> levels = new ArrayList<>(levelSize);
        long elementOrder = 0;
        long elementSmallerThanBound = 0;
        OrderedElement<T> mostUpperElement = null;
        OrderedElement<T> mostLowerElement = null;
        for (T unorderedElement : stream) {
            OrderedElement<T> element = new OrderedElement<>(unorderedElement, elementOrder++);

            elementSmallerThanBound = oldBounds.updateNumberOfElementsLower(element, comparator, elementSmallerThanBound);
            if (!oldBounds.isInBounds(element, comparator)) {
                continue;
            }
            mostUpperElement = max(mostUpperElement, element);
            mostLowerElement = min(mostLowerElement, element);
            if (isLevelFull(current)) {
                current = mergeUp(current, levels);
                Preconditions.checkArgument(current.isEmpty());
            }
            current.add(element);
        }
        finalizeTree(current, levels);
        Preconditions.checkArgument(kOrder < elementOrder, "K-order is bigger than stream size!");

        Preconditions.checkArgument(mostUpperElement != null && mostLowerElement != null);
        Preconditions.checkArgument(kOrder >= elementSmallerThanBound,
                "DEBUG: element before: " + elementSmallerThanBound + " order: " + kOrder);
        kOrder -= elementSmallerThanBound;
        if (levels.size() == 1) {
            OrderedElement<T> element = levels.get(0).get((int) kOrder);
            return new StrictBounds<>(element, element);
        }

        List<OrderedElement<T>> upperLevel = levels.get(levels.size() - 1);

        assert comparator.isOrdered(upperLevel);
        int lowerIndex = (int) ((kOrder ) / powerOfTwo(levels.size() - 1));
        int upperIndex = (int) ((kOrder ) / powerOfTwo(levels.size() - 1)) + levels.size() - 1;
        OrderedElement<T> lowerElement = lowerIndex >= 0 ?
                upperLevel.get(lowerIndex) : mostLowerElement;
        OrderedElement<T> upperElement = upperIndex < levelSize && !upperLevel.get(upperIndex).isInfinity() ?
                upperLevel.get(upperIndex) : mostUpperElement;
        System.gc();
        return new StrictBounds<>(
                lowerElement,
                upperElement);
    }