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

com.fluxtion.agrona.collections.IntArrayQueue Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014-2024 Real Logic Limited.
 *
 * 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
 *
 * https://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.fluxtion.agrona.collections;

import com.fluxtion.agrona.BitUtil;
import com.fluxtion.agrona.generation.DoNotSub;

import java.util.AbstractQueue;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.IntConsumer;

/**
 * Queue of ints which stores the elements without boxing. Null is represented by a special {@link #nullValue()}.
 * 

* The {@link IntIterator} is cached by default to avoid allocation unless directed to do so in the constructor. *

* Note: This class is not threadsafe. */ public class IntArrayQueue extends AbstractQueue { /** * Default representation of null for an element. */ public static final int DEFAULT_NULL_VALUE = Integer.MIN_VALUE; /** * Minimum capacity for the queue which must also be a power of 2. */ @DoNotSub public static final int MIN_CAPACITY = 8; private final boolean shouldAvoidAllocation; @DoNotSub private int head; @DoNotSub private int tail; private final int nullValue; private int[] elements; private IntIterator iterator; /** * Construct a new queue defaulting to {@link #MIN_CAPACITY} capacity, {@link #DEFAULT_NULL_VALUE} * and cached iterators. */ public IntArrayQueue() { this(MIN_CAPACITY, DEFAULT_NULL_VALUE, true); } /** * Construct a new queue defaulting to {@link #MIN_CAPACITY} capacity and cached iterators. * * @param nullValue cannot be stored in the queue and used as a sentinel. */ public IntArrayQueue(final int nullValue) { this(MIN_CAPACITY, nullValue, true); } /** * Construct a new queue default to cached iterators. * * @param initialCapacity for the queue which will be rounded up to the nearest power of 2. * @param nullValue which cannot be stored in the queue and used as a sentinel. */ public IntArrayQueue( @DoNotSub final int initialCapacity, final int nullValue) { this(initialCapacity, nullValue, true); } /** * Construct a new queue providing all the config options. * * @param initialCapacity for the queue which will be rounded up to the nearest power of 2. * @param nullValue which cannot be stored in the queue and used as a sentinel. * @param shouldAvoidAllocation true to cache the iterator otherwise false to allocate a new iterator each time. */ public IntArrayQueue( @DoNotSub final int initialCapacity, final int nullValue, final boolean shouldAvoidAllocation) { this.nullValue = nullValue; this.shouldAvoidAllocation = shouldAvoidAllocation; if (initialCapacity < MIN_CAPACITY) { throw new IllegalArgumentException("initial capacity < MIN_INITIAL_CAPACITY : " + initialCapacity); } @DoNotSub final int capacity = BitUtil.findNextPositivePowerOfTwo(initialCapacity); if (capacity < MIN_CAPACITY) { throw new IllegalArgumentException("invalid initial capacity: " + initialCapacity); } elements = new int[capacity]; Arrays.fill(elements, nullValue); } /** * The value representing a null element. * * @return value representing a null element. */ public int nullValue() { return nullValue; } /** * The current capacity for the collection. * * @return the current capacity for the collection. */ @DoNotSub public int capacity() { return elements.length; } /** * {@inheritDoc} */ @DoNotSub public int size() { return (tail - head) & (elements.length - 1); } /** * {@inheritDoc} */ public boolean isEmpty() { return head == tail; } /** * {@inheritDoc} */ public void clear() { if (head != tail) { Arrays.fill(elements, nullValue); head = 0; tail = 0; } } /** * {@inheritDoc} */ public boolean offer(final Integer element) { return offerInt(element); } /** * Offer an element to the tail of the queue without boxing. * * @param element to be offered to the queue. * @return will always be true as long as the underlying array can be expanded. */ public boolean offerInt(final int element) { if (nullValue == element) { throw new NullPointerException(); // @DoNotSub } elements[tail] = element; tail = (tail + 1) & (elements.length - 1); if (tail == head) { increaseCapacity(); } return true; } /** * {@inheritDoc} */ public boolean add(final Integer element) { return offerInt(element); } /** * Offer an element to the tail of the queue without boxing. * * @param element to be offered to the queue. * @return will always be true as long as the underlying array can be expanded. */ public boolean addInt(final int element) { return offerInt(element); } /** * {@inheritDoc} */ public Integer peek() { final int element = elements[head]; return element == nullValue ? null : element; } /** * Peek at the element on the head of the queue without boxing. * * @return the element at the head of the queue without removing it. */ public int peekInt() { return elements[head]; } /** * {@inheritDoc} */ public Integer poll() { final int element = pollInt(); return element == nullValue ? null : element; } /** * Poll the element from the head of the queue without boxing. * * @return the element at the head of the queue removing it. If empty then {@link #nullValue}. */ public int pollInt() { final int element = elements[head]; if (nullValue == element) { return nullValue; } elements[head] = nullValue; head = (head + 1) & (elements.length - 1); return element; } /** * {@inheritDoc} */ public Integer remove() { final int element = pollInt(); if (nullValue == element) { throw new NoSuchElementException(); } return element; } /** * {@inheritDoc} */ public Integer element() { final int element = elements[head]; if (nullValue == element) { throw new NoSuchElementException(); } return element; } /** * Peek at the element on the head of the queue without boxing. * * @return the element at the head of the queue without removing it. * @throws NoSuchElementException if the queue is empty. */ public int elementInt() { final int element = elements[head]; if (nullValue == element) { throw new NoSuchElementException(); } return element; } /** * Remove the element at the head of the queue without boxing. * * @return the element at the head of the queue. * @throws NoSuchElementException if the queue is empty. */ public int removeInt() { final int element = pollInt(); if (nullValue == element) { throw new NoSuchElementException(); } return element; } /** * {@inheritDoc} */ public String toString() { final StringBuilder sb = new StringBuilder(); sb.append('['); for (@DoNotSub int i = head; i != tail; ) { sb.append(elements[i]).append(", "); i = (i + 1) & (elements.length - 1); } if (sb.length() > 1) { sb.setLength(sb.length() - 2); } sb.append(']'); return sb.toString(); } /** * {@inheritDoc} */ public void forEach(final Consumer action) { for (@DoNotSub int i = head; i != tail; ) { action.accept(elements[i]); i = (i + 1) & (elements.length - 1); } } /** * Iterate over the collection without boxing. * * @param action to be taken for each element. */ public void forEachInt(final IntConsumer action) { for (@DoNotSub int i = head; i != tail; ) { action.accept(elements[i]); i = (i + 1) & (elements.length - 1); } } /** * {@inheritDoc} */ public IntIterator iterator() { IntIterator iterator = this.iterator; if (null == iterator) { iterator = new IntIterator(); if (shouldAvoidAllocation) { this.iterator = iterator; } } return iterator.reset(); } private void increaseCapacity() { @DoNotSub final int oldHead = head; @DoNotSub final int oldCapacity = elements.length; @DoNotSub final int toEndOfArray = oldCapacity - oldHead; @DoNotSub final int newCapacity = oldCapacity << 1; if (newCapacity < MIN_CAPACITY) { throw new IllegalStateException("max capacity reached"); } final int[] array = new int[newCapacity]; Arrays.fill(array, oldCapacity, newCapacity, nullValue); System.arraycopy(elements, oldHead, array, 0, toEndOfArray); System.arraycopy(elements, 0, array, toEndOfArray, oldHead); elements = array; head = 0; tail = oldCapacity; } /** * Specialised {@link Iterator} from which the value can be retrieved without boxing via {@link #nextValue()}. */ public final class IntIterator implements Iterator { @DoNotSub private int index; IntIterator reset() { index = IntArrayQueue.this.head; return this; } /** * {@inheritDoc} */ public boolean hasNext() { return index != tail; } /** * {@inheritDoc} */ public Integer next() { return nextValue(); } /** * Get the next value from the iterator without boxing. * * @return the next value from the queue. */ public int nextValue() { if (index == tail) { throw new NoSuchElementException(); } final int element = elements[index]; index = (index + 1) & (elements.length - 1); return element; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy