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

one.util.streamex.RangeBasedSpliterator Maven / Gradle / Ivy

There is a newer version: 0.8.3
Show newest version
/*
 * Copyright 2015, 2016 Tagir Valeev
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package one.util.streamex;

import java.util.List;
import java.util.Map.Entry;
import java.util.Spliterator;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;

import static one.util.streamex.StreamExInternals.*;

/**
 * @author Tagir Valeev
 */
/* package */abstract class RangeBasedSpliterator> extends CloneableSpliterator {
    int cur;
    int limit;

    public RangeBasedSpliterator(int fromInclusive, int toExclusive) {
        this.cur = fromInclusive;
        this.limit = toExclusive;
    }

    @Override
    public long estimateSize() {
        return limit - cur;
    }

    @Override
    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }

    @Override
    public S trySplit() {
        int size = limit - cur;
        if (size >= 2) {
            S clone = doClone();
            clone.limit = this.cur = this.cur + size / 2;
            return clone;
        }
        return null;
    }

    static final class AsEntry extends RangeBasedSpliterator, AsEntry> {
        private final List list;

        public AsEntry(List list) {
            super(0, list.size());
            this.list = list;
        }

        @Override
        public boolean tryAdvance(Consumer> action) {
            if (cur < limit) {
                action.accept(new ObjIntBox<>(list.get(cur), cur));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(Consumer> action) {
            int l = limit, c = cur;
            List list = this.list;
            while (c < l) {
                action.accept(new ObjIntBox<>(list.get(c), c));
                c++;
            }
            cur = limit;
        }
    }

    static final class OfSubLists extends RangeBasedSpliterator, OfSubLists> {
        private final List source;
        private final int length;
        private final int shift;
        private final int listSize;

        public OfSubLists(List source, int length, int shift) {
            super(0, Math.max(0, source.size() - Math.max(length - shift, 0) - 1) / shift + 1);
            this.source = source;
            this.listSize = source.size();
            this.shift = shift;
            this.length = length;
        }

        @Override
        public boolean tryAdvance(Consumer> action) {
            if (cur < limit) {
                int start = cur * shift;
                int stop = listSize - length > start ? start + length : listSize;
                action.accept(source.subList(start, stop));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(Consumer> action) {
            int l = limit, c = cur, ll = length, sf = shift, ls = listSize;
            int start = cur * sf;
            while (c < l) {
                int stop = ls - ll > start ? start + ll : ls;
                action.accept(source.subList(start, stop));
                start += sf;
                c++;
            }
            cur = limit;
        }
    }

    static final class ZipRef extends RangeBasedSpliterator> {
        private final List l1;
        private final List l2;
        private final BiFunction mapper;

        public ZipRef(int fromInclusive, int toExclusive, BiFunction mapper,
                List l1, List l2) {
            super(fromInclusive, toExclusive);
            this.l1 = l1;
            this.l2 = l2;
            this.mapper = mapper;
        }

        @Override
        public boolean tryAdvance(Consumer action) {
            if (cur < limit) {
                action.accept(mapper.apply(l1.get(cur), l2.get(cur)));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(Consumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(mapper.apply(l1.get(c), l2.get(c)));
                c++;
            }
            cur = limit;
        }
    }

    static final class ZipInt extends RangeBasedSpliterator implements Spliterator.OfInt {
        private final IntBinaryOperator mapper;
        private final int[] arr1, arr2;

        public ZipInt(int fromInclusive, int toExclusive, IntBinaryOperator mapper, int[] arr1, int[] arr2) {
            super(fromInclusive, toExclusive);
            this.mapper = mapper;
            this.arr1 = arr1;
            this.arr2 = arr2;
        }

        @Override
        public boolean tryAdvance(IntConsumer action) {
            if (cur < limit) {
                action.accept(mapper.applyAsInt(arr1[cur], arr2[cur]));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(mapper.applyAsInt(arr1[c], arr2[c]));
                c++;
            }
            cur = limit;
        }
    }

    static final class OfByte extends RangeBasedSpliterator implements Spliterator.OfInt {
        private final byte[] array;

        public OfByte(int fromInclusive, int toExclusive, byte[] array) {
            super(fromInclusive, toExclusive);
            this.array = array;
        }

        @Override
        public boolean tryAdvance(IntConsumer action) {
            if (cur < limit) {
                action.accept(array[cur]);
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(array[c++]);
            }
            cur = limit;
        }
    }

    static final class OfChar extends RangeBasedSpliterator implements Spliterator.OfInt {
        private final char[] array;

        public OfChar(int fromInclusive, int toExclusive, char[] array) {
            super(fromInclusive, toExclusive);
            this.array = array;
        }

        @Override
        public boolean tryAdvance(IntConsumer action) {
            if (cur < limit) {
                action.accept(array[cur]);
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(array[c++]);
            }
            cur = limit;
        }
    }

    static final class OfShort extends RangeBasedSpliterator implements Spliterator.OfInt {
        private final short[] array;

        public OfShort(int fromInclusive, int toExclusive, short[] array) {
            super(fromInclusive, toExclusive);
            this.array = array;
        }

        @Override
        public boolean tryAdvance(IntConsumer action) {
            if (cur < limit) {
                action.accept(array[cur]);
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(IntConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(array[c++]);
            }
            cur = limit;
        }
    }

    static final class ZipLong extends RangeBasedSpliterator implements Spliterator.OfLong {
        private final LongBinaryOperator mapper;
        private final long[] arr1, arr2;

        public ZipLong(int fromInclusive, int toExclusive, LongBinaryOperator mapper, long[] arr1, long[] arr2) {
            super(fromInclusive, toExclusive);
            this.mapper = mapper;
            this.arr1 = arr1;
            this.arr2 = arr2;
        }

        @Override
        public boolean tryAdvance(LongConsumer action) {
            if (cur < limit) {
                action.accept(mapper.applyAsLong(arr1[cur], arr2[cur]));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(LongConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(mapper.applyAsLong(arr1[c], arr2[c]));
                c++;
            }
            cur = limit;
        }
    }

    static final class OfFloat extends RangeBasedSpliterator implements Spliterator.OfDouble {
        private final float[] array;

        public OfFloat(int fromInclusive, int toExclusive, float[] array) {
            super(fromInclusive, toExclusive);
            this.array = array;
        }

        @Override
        public boolean tryAdvance(DoubleConsumer action) {
            if (cur < limit) {
                action.accept(array[cur]);
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(DoubleConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(array[c++]);
            }
            cur = limit;
        }
    }

    static final class ZipDouble extends RangeBasedSpliterator implements Spliterator.OfDouble {
        private final DoubleBinaryOperator mapper;
        private final double[] arr1, arr2;

        public ZipDouble(int fromInclusive, int toExclusive, DoubleBinaryOperator mapper, double[] arr1, double[] arr2) {
            super(fromInclusive, toExclusive);
            this.mapper = mapper;
            this.arr1 = arr1;
            this.arr2 = arr2;
        }

        @Override
        public boolean tryAdvance(DoubleConsumer action) {
            if (cur < limit) {
                action.accept(mapper.applyAsDouble(arr1[cur], arr2[cur]));
                cur++;
                return true;
            }
            return false;
        }

        @Override
        public void forEachRemaining(DoubleConsumer action) {
            int l = limit, c = cur;
            while (c < l) {
                action.accept(mapper.applyAsDouble(arr1[c], arr2[c]));
                c++;
            }
            cur = limit;
        }
    }
}