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

com.landawn.abacus.util.stream.SpinedBuffer Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.2.4
Show newest version
/*
 * Copyright (C) 2021 HaiYang Li
 *
 * 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 com.landawn.abacus.util.stream;

import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;

import com.landawn.abacus.util.DoubleIterator;
import com.landawn.abacus.util.IntIterator;
import com.landawn.abacus.util.LongIterator;
import com.landawn.abacus.util.N;
import com.landawn.abacus.util.ObjIterator;

/**
 *
 *
 * @param 
 */
final class SpinedBuffer extends AbstractCollection implements Consumer {
    private static final int CHUNK_SIZE = 9;
    private static final int SPINE_SIZE_TO_INCREASE = 8;

    private E[][] spine = null; //NOSONAR
    private E[] curChunk = (E[]) N.EMPTY_OBJECT_ARRAY; //NOSONAR
    private int size = 0; //NOSONAR

    public SpinedBuffer() {
        this(CHUNK_SIZE);
    }

    public SpinedBuffer(int initialCapacity) {
        N.checkArgNotNegative(initialCapacity, "initialCapacity"); //NOSONAR

        if (initialCapacity > 0) {
            this.curChunk = (E[]) new Object[initialCapacity];
        }
    }

    @Override
    public void accept(E t) {
        this.add(t);
    }

    @Override
    public boolean add(E e) {
        if (size < curChunk.length) {
            curChunk[size] = e;
        } else if (curChunk.length == 0) {
            this.curChunk = (E[]) new Object[CHUNK_SIZE];
            curChunk[size] = e;
        } else {
            if (spine == null) {
                spine = (E[][]) new Object[SPINE_SIZE_TO_INCREASE][];
                spine[0] = curChunk;
                spine[1] = (E[]) new Object[CHUNK_SIZE];
                curChunk = spine[1];
            } else {
                final int chunkIndex = (size - spine[0].length) / CHUNK_SIZE + 1;

                if (spine.length <= chunkIndex) {
                    spine = N.copyOf(spine, spine.length + SPINE_SIZE_TO_INCREASE);
                }

                if (spine[chunkIndex] == null) {
                    curChunk = (E[]) new Object[CHUNK_SIZE];
                    spine[chunkIndex] = curChunk;
                }
            }

            curChunk[(size - spine[0].length) % CHUNK_SIZE] = e;
        }

        size++;
        return true;
    }

    /**
     * @param o
     * @throws UnsupportedOperationException
     * @deprecated Unsupported operation.
     */
    @Deprecated
    @Override
    public boolean remove(Object o) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    /**
     * @param c
     * @throws UnsupportedOperationException
     * @deprecated Unsupported operation.
     */
    @Deprecated
    @Override
    public boolean removeAll(Collection c) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator iterator() {
        if (N.isNullOrEmpty(spine)) {
            return ObjIterator.of(curChunk, 0, size);
        } else {
            final int localSize = size();

            return new ObjIterator<>() {
                private final E[] firstChunk = spine[0];
                private final int firstChunkLen = firstChunk.length;
                private int cursor = 0;
                private E next = null;

                @Override
                public boolean hasNext() {
                    return cursor < localSize;
                }

                @Override
                public E next() {
                    if (cursor >= localSize) {
                        throw new NoSuchElementException();
                    }

                    if (cursor < firstChunkLen) {
                        return firstChunk[cursor++];
                    } else {
                        next = spine[(cursor - firstChunkLen) / CHUNK_SIZE + 1][(cursor - firstChunkLen) % CHUNK_SIZE];

                        cursor++;

                        return next;
                    }
                }
            };
        }
    }

    @Override
    public int size() {
        return size;
    }

    static class OfInt implements IntConsumer {
        private int[][] spine = null;
        private int[] curChunk = N.EMPTY_INT_ARRAY;
        private int size = 0;

        public OfInt() {
            this(CHUNK_SIZE);
        }

        public OfInt(int initialCapacity) {
            N.checkArgNotNegative(initialCapacity, "initialCapacity");

            if (initialCapacity > 0) {
                this.curChunk = new int[initialCapacity];
            }
        }

        @Override
        public void accept(int t) {
            this.add(t);
        }

        public boolean add(int e) {
            if (size < curChunk.length) {
                curChunk[size] = e;
            } else if (curChunk.length == 0) {
                this.curChunk = new int[CHUNK_SIZE];
                curChunk[size] = e;
            } else {
                if (spine == null) {
                    spine = new int[SPINE_SIZE_TO_INCREASE][];
                    spine[0] = curChunk;
                    spine[1] = new int[CHUNK_SIZE];
                    curChunk = spine[1];
                } else {
                    final int chunkIndex = (size - spine[0].length) / CHUNK_SIZE + 1;

                    if (spine.length <= chunkIndex) {
                        spine = N.copyOf(spine, spine.length + SPINE_SIZE_TO_INCREASE);
                    }

                    if (spine[chunkIndex] == null) {
                        curChunk = new int[CHUNK_SIZE];
                        spine[chunkIndex] = curChunk;
                    }
                }

                curChunk[(size - spine[0].length) % CHUNK_SIZE] = e;
            }

            size++;
            return true;
        }

        public IntIterator iterator() {
            if (N.isNullOrEmpty(spine)) {
                return IntIterator.of(curChunk, 0, size);
            } else {
                final int localSize = size();

                return new IntIterator() {
                    private final int[] firstChunk = spine[0];
                    private final int firstChunkLen = firstChunk.length;
                    private int cursor = 0;
                    private int next = 0;

                    @Override
                    public boolean hasNext() {
                        return cursor < localSize;
                    }

                    @Override
                    public int nextInt() {
                        if (cursor >= localSize) {
                            throw new NoSuchElementException();
                        }

                        if (cursor < firstChunkLen) {
                            return firstChunk[cursor++];
                        } else {
                            next = spine[(cursor - firstChunkLen) / CHUNK_SIZE + 1][(cursor - firstChunkLen) % CHUNK_SIZE];

                            cursor++;

                            return next;
                        }
                    }
                };
            }
        }

        public int size() {
            return size;
        }
    }

    static class OfLong implements LongConsumer {
        private long[][] spine = null;
        private long[] curChunk = N.EMPTY_LONG_ARRAY;
        private int size = 0;

        public OfLong() {
            this(CHUNK_SIZE);
        }

        public OfLong(int initialCapacity) {
            N.checkArgNotNegative(initialCapacity, "initialCapacity");

            if (initialCapacity > 0) {
                this.curChunk = new long[initialCapacity];
            }
        }

        @Override
        public void accept(long t) {
            this.add(t);
        }

        public boolean add(long e) {
            if (size < curChunk.length) {
                curChunk[size] = e;
            } else if (curChunk.length == 0) {
                this.curChunk = new long[CHUNK_SIZE];
                curChunk[size] = e;
            } else {
                if (spine == null) {
                    spine = new long[SPINE_SIZE_TO_INCREASE][];
                    spine[0] = curChunk;
                    spine[1] = new long[CHUNK_SIZE];
                    curChunk = spine[1];
                } else {
                    final int chunkIndex = (size - spine[0].length) / CHUNK_SIZE + 1;

                    if (spine.length <= chunkIndex) {
                        spine = N.copyOf(spine, spine.length + SPINE_SIZE_TO_INCREASE);
                    }

                    if (spine[chunkIndex] == null) {
                        curChunk = new long[CHUNK_SIZE];
                        spine[chunkIndex] = curChunk;
                    }
                }

                curChunk[(size - spine[0].length) % CHUNK_SIZE] = e;
            }

            size++;
            return true;
        }

        public LongIterator iterator() {
            if (N.isNullOrEmpty(spine)) {
                return LongIterator.of(curChunk, 0, size);
            } else {
                final int localSize = size();

                return new LongIterator() {
                    private final long[] firstChunk = spine[0];
                    private final int firstChunkLen = firstChunk.length;
                    private int cursor = 0;
                    private long next = 0;

                    @Override
                    public boolean hasNext() {
                        return cursor < localSize;
                    }

                    @Override
                    public long nextLong() {
                        if (cursor >= localSize) {
                            throw new NoSuchElementException();
                        }

                        if (cursor < firstChunkLen) {
                            return firstChunk[cursor++];
                        } else {
                            next = spine[(cursor - firstChunkLen) / CHUNK_SIZE + 1][(cursor - firstChunkLen) % CHUNK_SIZE];

                            cursor++;

                            return next;
                        }
                    }
                };
            }
        }

        public int size() {
            return size;
        }
    }

    static class OfDouble implements DoubleConsumer {
        private double[][] spine = null;
        private double[] curChunk = N.EMPTY_DOUBLE_ARRAY;
        private int size = 0;

        public OfDouble() {
            this(CHUNK_SIZE);
        }

        public OfDouble(int initialCapacity) {
            N.checkArgNotNegative(initialCapacity, "initialCapacity");

            if (initialCapacity > 0) {
                this.curChunk = new double[initialCapacity];
            }
        }

        @Override
        public void accept(double t) {
            this.add(t);
        }

        public boolean add(double e) {
            if (size < curChunk.length) {
                curChunk[size] = e;
            } else if (curChunk.length == 0) {
                this.curChunk = new double[CHUNK_SIZE];
                curChunk[size] = e;
            } else {
                if (spine == null) {
                    spine = new double[SPINE_SIZE_TO_INCREASE][];
                    spine[0] = curChunk;
                    spine[1] = new double[CHUNK_SIZE];
                    curChunk = spine[1];
                } else {
                    final int chunkIndex = (size - spine[0].length) / CHUNK_SIZE + 1;

                    if (spine.length <= chunkIndex) {
                        spine = N.copyOf(spine, spine.length + SPINE_SIZE_TO_INCREASE);
                    }

                    if (spine[chunkIndex] == null) {
                        curChunk = new double[CHUNK_SIZE];
                        spine[chunkIndex] = curChunk;
                    }
                }

                curChunk[(size - spine[0].length) % CHUNK_SIZE] = e;
            }

            size++;
            return true;
        }

        public DoubleIterator iterator() {
            if (N.isNullOrEmpty(spine)) {
                return DoubleIterator.of(curChunk, 0, size);
            } else {
                final int localSize = size();

                return new DoubleIterator() {
                    private final double[] firstChunk = spine[0];
                    private final int firstChunkLen = firstChunk.length;
                    private int cursor = 0;
                    private double next = 0;

                    @Override
                    public boolean hasNext() {
                        return cursor < localSize;
                    }

                    @Override
                    public double nextDouble() {
                        if (cursor >= localSize) {
                            throw new NoSuchElementException();
                        }

                        if (cursor < firstChunkLen) {
                            return firstChunk[cursor++];
                        } else {
                            next = spine[(cursor - firstChunkLen) / CHUNK_SIZE + 1][(cursor - firstChunkLen) % CHUNK_SIZE];

                            cursor++;

                            return next;
                        }
                    }
                };
            }
        }

        public int size() {
            return size;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy