com.groupon.lex.metrics.lib.SkippingIterator.java Source code

Java tutorial

Introduction

Here is the source code for com.groupon.lex.metrics.lib.SkippingIterator.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.groupon.lex.metrics.lib;

import java.util.Iterator;
import static java.util.Objects.requireNonNull;
import java.util.Spliterator;
import static java.util.Spliterator.IMMUTABLE;
import static java.util.Spliterator.NONNULL;
import static java.util.Spliterator.ORDERED;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;

/**
 *
 * @author ariane
 */
public class SkippingIterator<T> implements Iterator<T> {
    private final Iterator<T> underlying_;
    private final Function<? super T, ? extends DateTime> timestamp_fn_;
    private final Duration stepsize_;
    private T next_;
    private DateTime expected_ts_ = new DateTime(0L, DateTimeZone.UTC);

    public SkippingIterator(Iterator<T> underlying, Function<? super T, ? extends DateTime> timestamp_fn,
            Duration stepsize) {
        underlying_ = requireNonNull(underlying);
        timestamp_fn_ = requireNonNull(timestamp_fn);
        stepsize_ = requireNonNull(stepsize);
        next_ = null;
    }

    public static <T> Stream<T> adaptStream(Stream<T> stream, Function<? super T, ? extends DateTime> timestamp_fn,
            Duration stepsize) {
        if (stepsize.getMillis() <= 0L)
            return stream;

        final Iterator<T> iter = new SkippingIterator<>(stream.iterator(), timestamp_fn, stepsize);
        final Spliterator<T> spliter = Spliterators.spliteratorUnknownSize(iter, NONNULL | IMMUTABLE | ORDERED);
        return StreamSupport.stream(spliter, false);
    }

    @Override
    public boolean hasNext() {
        fixup_next_();
        return next_ != null;
    }

    @Override
    public T next() {
        fixup_next_();
        final T next = next_;
        next_ = null;
        return next;
    }

    private void fixup_next_() {
        while (next_ == null && underlying_.hasNext()) {
            final T next = underlying_.next();
            final DateTime next_ts = timestamp_fn_.apply(next);
            if (!next_ts.isBefore(expected_ts_)) {
                next_ = next;
                expected_ts_ = next_ts.plus(stepsize_);
            }
        }
    }
}