All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.phantomthief.util.CursorIterator Maven / Gradle / Ivy

The newest version!
/**
 * 
 */
package com.github.phantomthief.util;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 
 * @author w.vela
 */
public class CursorIterator implements Iterable {

    private static final int DEFAULT_BUFFER_SIZE = 30;

    private final GetByCursorDAO dao;
    private final int bufferSize;
    private final Function function;

    private Id initCursor;
    private boolean firstTime;
    private boolean end;

    /**
     * @param dao 游标方式取的DAO
     * @param initCursor 第一次的游标位置(包含)
     * @param bufferSize 每次游标迭代的条数
     * @param extractor 游标和实体数据的转换器
     * 
     * better use {@code #newBuilder()}
     */
    @Deprecated
    public CursorIterator(GetByCursorDAO dao, Id initCursor, int bufferSize,
            Function extractor) {
        checkArgument(bufferSize > 0);
        checkNotNull(dao);
        checkNotNull(extractor);

        this.dao = dao;
        this.initCursor = initCursor;
        this.bufferSize = bufferSize;
        this.firstTime = true;
        this.function = extractor;
        this.end = false;
    }

    private List innerData;

    private List innerData() {
        if (end) {
            return Collections.emptyList();
        }
        if (innerData == null) {
            innerData = dao.getByCursor(initCursor, firstTime ? bufferSize : bufferSize + 1);
            if ((innerData.size() > 0) && !firstTime) {
                innerData = innerData.subList(1, innerData.size());
            }
        }
        return innerData;
    }

    /**
     * 取到内部迭代器
     * 
     * @return
     */
    private Iterator innerIterator() {
        return innerData().iterator();
    }

    /**
     * 下一个迭代时拿上一次游标的位置
     * 
     * @return
     */
    private Id getLastCursor() {
        List byCursor = innerData();
        if (byCursor == null || byCursor.isEmpty()) {
            return null;
        }
        Id result = function.apply(byCursor.get(byCursor.size() - 1));
        return result;
    }

    /**
     * 判断是否到结尾的标记
     * 
     * @return
     */
    private boolean hasMore() {
        List byCurosr = innerData();
        if (byCurosr.size() < bufferSize) {
            return false;
        } else {
            return true;
        }
    }

    /* (non-Javadoc)
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator iterator() {
        /**
         * 这个匿名类主要做lazy的用途,可以在迭代的过程中,不会把所有的数据和迭代器都生成,只生成最近两个的
         */
        return new Iterator() {

            private Iterator itr;

            private Iterator itr() {
                if (itr == null) {
                    itr = innerIterator();
                }
                return itr;
            }

            @Override
            public boolean hasNext() {
                boolean hasNext = itr().hasNext();
                if (!hasNext) {
                    if (end) {
                        return hasNext;
                    } else {
                        initCursor = getLastCursor();
                        firstTime = false;
                        end = !hasMore();
                        innerData = null;
                        itr = null;
                        return itr().hasNext();
                    }
                }
                return hasNext;
            }

            @Override
            public Entity next() {
                return itr().next();
            }

            @Override
            public void remove() {
                itr().remove();
            }
        };
    }

    public Stream stream() {
        return StreamSupport.stream(
                Spliterators.spliteratorUnknownSize(iterator(),
                        (Spliterator.NONNULL | Spliterator.IMMUTABLE | Spliterator.ORDERED)),
                false);
    }

    @SuppressWarnings("unchecked")
    public static final class Builder {

        private GetByCursorDAO dao;
        private int bufferSize;
        private Function function;
        private Id init;

        public  CursorIterator build(GetByCursorDAO dao) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.dao = (GetByCursorDAO) dao;
            return thisBuilder.build();
        }

        public Builder bufferSize(int bufferSize) {
            this.bufferSize = bufferSize;
            return this;
        }

        public  Builder cursorExtractor(Function function) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.function = (Function) function;
            return thisBuilder;
        }

        public  Builder start(I init) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.init = init;
            return thisBuilder;
        }

        private CursorIterator build() {
            ensure();
            return new CursorIterator<>(dao, init, bufferSize, function);
        }

        private void ensure() {
            checkNotNull(dao);
            checkNotNull(function);

            if (bufferSize <= 0) {
                bufferSize = DEFAULT_BUFFER_SIZE;
            }
        }
    }

    public static Builder newBuilder() {
        return new Builder<>();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy