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

com.tangosol.util.Dequeue Maven / Gradle / Ivy

There is a newer version: 24.03
Show newest version
/*
 * Copyright (c) 2000, 2020, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

package com.tangosol.util;


import java.io.Serializable;

import java.util.Iterator;
import java.util.Enumeration;
import java.util.NoSuchElementException;


/**
* Represents a double-ended queue (dequeue) of objects.  A dequeue allows
* items which have been removed from the front of the queue to be put back
* on the front of the queue.
*
* @version 1.00, 12/05/96
* @author 	Cameron Purdy
*/
public class Dequeue
        extends Base
        implements Enumeration, Iterator, Cloneable, Serializable
    {
    // ----- constructors ---------------------------------------------------

    /**
    * Constructs a dequeue.
    */
    public Dequeue()
        {
        removeAllElements();
        }


    // ----- Enumeration interface ------------------------------------------

    /**
    * Determines if the Dequeue contains more elements.
    *
    * @return true if Dequeue contains more elements, false otherwise
    */
    public boolean hasMoreElements()
        {
        return !isEmpty();
        }

    /**
    * Returns the next element from the Dequeue.  Calls to this method will
    * enumerate successive elements.
    *
    * @return the next element
    *
    * @exception NoSuchElementException If no more elements exist.
    */
    public Object nextElement() throws NoSuchElementException
        {
        if (isEmpty())
            {
            throw new NoSuchElementException();
            }

        // get the next element
        m_iFront = next(m_iFront);
        Object o = m_aoItem[m_iFront];

        // release the reference to the next element (allows it to be gc'd)
        m_aoItem[m_iFront] = null;

        return o;
        }


    // ----- Iterator interface ---------------------------------------------

    /**
    * Tests if this Iterator contains more elements.
    *
    * @return true if the Iterator contains more elements, false otherwise
    */
    public boolean hasNext()
        {
        return !isEmpty();
        }

    /**
    * Returns the next element of this Iterator.
    *
    * @return the next element in the Iterator
    */
    public Object next()
        {
        return nextElement();
        }

    /**
    * Remove the last-returned element that was returned by the Iterator.
    * This method always throws UnsupportedOperationException because the
    * Iterator is immutable.
    */
    public void remove()
        {
        throw new UnsupportedOperationException("iterator is immutable");
        }


    // ----- Dequeue interface ----------------------------------------------

    /**
    * Adds an element to the dequeue.  The passed object is placed at the end
    * of the dequeue.
    *
    * @param o object to add to the Dequeue
    */
    public void addElement(Object o)
        {
        if (isFull())
            {
            grow();
            }

        m_iBack = next(m_iBack);
        m_aoItem[m_iBack] = o;
        }

    /**
    * Returns the most recently returned element to the Dequeue.  After calling
    * this method, a call to nextElement will return the element that was
    * returned by the most recent call to nextElement.  This method can be
    * called multiple times to put back multiple elements.
    *
    * @param o  the object
    *
    * @exception NoSuchElementException If the element that is being put back
    *            is no longer in the Dequeue.
    */
    public void putBackElement(Object o)
        {
        if (isFull())
            {
            grow();
            }

        m_aoItem[m_iFront] = o;
        m_iFront = prev(m_iFront);
        }

    /**
    * Removes all items from the dequeue.
    */
    public void removeAllElements()
        {
        m_aoItem = new Object [DEFAULT_MAX_ELEMENTS];
        m_iFront = 0;
        m_iBack  = 0;
        }

    /**
    * Determine the current capacity of this dequeue.
    *
    * @return the current capacity of this dequeue
    */
    public int capacity()
        {
        return m_aoItem.length - 1;
        }

    /**
    * Determine the current number of objects in this dequeue.
    *
    * @return the current number of objects in this dequeue
    */
    public int size()
        {
        if (m_iFront <= m_iBack)
            {
            return m_iBack - m_iFront;
            }
        else
            {
            return m_aoItem.length - (m_iFront - m_iBack);
            }
        }

    /**
    * Determines if the dequeue is empty.
    *
    * @return true if the dequeue is empty, false otherwise
    */
    public boolean isEmpty()
        {
        return (m_iFront == m_iBack);
        }

    /**
    * Determines if the dequeue is full.  This method is mainly of use
    * internally, since the dequeue auto-resizes when additional items are
    * added.
    *
    * @return true if the dequeue is full, false otherwise
    */
    public boolean isFull()
        {
        return (m_iFront == next(m_iBack));
        }


    // ----- Object methods -------------------------------------------------

    /**
    * Creates a clone of the dequeue.
    *
    * @return the clone
    */
    public Object clone()
        {
        try
            {
            Dequeue that = (Dequeue) super.clone();
            that.m_aoItem = (Object[]) that.m_aoItem.clone();
            return that;
            }
        catch (Exception e)
            {
            throw ensureRuntimeException(e);
            }
        }


    // ----- internal methods -----------------------------------------------

    /**
    * Determines the index following the passed index for storing or
    * accessing an item from the m_ao storage.
    *
    * @param i  the index
    *
    * @return the next index
    */
    protected int next(int i)
        {
        return (++i == m_aoItem.length ? 0 : i);
        }

    /**
    * Determines the index preceding the passed index for storing or
    * accessing an item from the m_ao storage.
    *
    * @param i  the index
    *
    * @return the previous index
    */
    protected int prev(int i)
        {
        return (i == 0 ? m_aoItem.length - 1 : --i);
        }

    /**
    * Increase the capacity of the Dequeue.
    */
    protected void grow()
        {
        // grow by 50%, but by 32 minimum or 256 maximum
        int cOld = m_aoItem.length;
        int cNew = cOld + Math.max(Math.min(cOld >> 1, 256), 32);

        // create new array and copy existing elements to it
        Object [] aoNew = new Object [cNew];
        if (m_iFront < m_iBack)
            {
            System.arraycopy(m_aoItem, m_iFront, aoNew, m_iFront, m_iBack - m_iFront + 1);
            }
        else if (m_iFront > m_iBack)
            {
            System.arraycopy(m_aoItem, 0, aoNew, 0, m_iBack + 1);
            System.arraycopy(m_aoItem, m_iFront, aoNew, cNew - (cOld - m_iFront), cOld - m_iFront);
            m_iFront += cNew - cOld;
            }

        m_aoItem = aoNew;
        }


    // ----- constants ------------------------------------------------------

    /**
    * Default dequeue size.
    */
    private static final int DEFAULT_MAX_ELEMENTS   = 32;


    // ----- data members ---------------------------------------------------

    /**
    * The storage for the objects in the dequeue.
    */
    Object[] m_aoItem;

    /**
    * The front of the queue, which is the next element to return.
    */
    int m_iFront;

    /**
    * The back of the queue, which is the last element that can be returned.
    */
    int m_iBack;
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy