001/* Copyright (C) 2013 TU Dortmund
002 * This file is part of AutomataLib, http://www.automatalib.net/.
003 * 
004 * AutomataLib is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License version 3.0 as published by the Free Software Foundation.
007 * 
008 * AutomataLib is distributed in the hope that it will be useful,
009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
011 * Lesser General Public License for more details.
012 * 
013 * You should have received a copy of the GNU Lesser General Public
014 * License along with AutomataLib; if not, see
015 * http://www.gnu.de/documents/lgpl.en.html.
016 */
017package net.automatalib.commons.util.array;
018
019
020/**
021 * Class that provides a resizable {@link Object} array storage.
022 * 
023 * Unlike {@link ResizingArrayStorage}, the array provided by this class
024 * is always of type <code>Object[]</code>. This results in a higher efficiency,
025 * since there is no need for reflection when creating new arrays.
026 * 
027 * @author Malte Isberner <malte.isberner@gmail.com>
028 *
029 */
030public final class ResizingObjectArray {
031        
032        /**
033         * The arrays default initial capacity.
034         */
035        public static final int DEFAULT_INITIAL_CAPACITY = 10;
036        
037        /**
038         * The storage array.
039         */
040        public Object[] array;
041        
042        private int nextCapacityHint;
043        
044        
045        /**
046         * Constructor. Initializes an array of the default initial capacity.
047         * @see #DEFAULT_INITIAL_CAPACITY
048         */
049        public ResizingObjectArray() {
050                this(DEFAULT_INITIAL_CAPACITY);
051        }
052        
053        /**
054         * Constructor. Creates an array with the specified initial capacity.
055         * 
056         * @param initialCapacity the initial capacity.
057         */
058        public ResizingObjectArray(int initialCapacity) {
059                if(initialCapacity <= 0)
060                        initialCapacity = DEFAULT_INITIAL_CAPACITY;
061                this.array = new Object[initialCapacity];
062        }
063        
064        /**
065         * Hints the next required capacity. The next time the array is resized, it
066         * is resized to (at least) this capacity.
067         * @param nextCapacityHint the next capacity hint.
068         */
069        public void hintNextCapacity(int nextCapacityHint) {
070                this.nextCapacityHint = nextCapacityHint;
071        }
072        
073        
074        public boolean ensureCapacity(int minCapacity) {
075                if (minCapacity <= array.length)
076                        return false;
077
078                int newCapacity = (array.length * 3) / 2 + 1;
079                if (newCapacity < nextCapacityHint)
080                        newCapacity = nextCapacityHint;
081
082                if (newCapacity < minCapacity)
083                        newCapacity = minCapacity;
084
085                Object[] newArray = new Object[newCapacity];
086                System.arraycopy(array, 0, newArray, 0, array.length);
087                array = newArray;
088                nextCapacityHint = 0;
089                return true;
090        }
091        
092        public boolean shrink(int maxCapacity) {
093                if(maxCapacity >= array.length)
094                        return false;
095                
096                Object[] newArray = new Object[maxCapacity];
097                System.arraycopy(array, 0, newArray, 0, maxCapacity);
098                array = newArray;
099                return true;
100        }
101
102        /**
103         * Sets all the elements in the array to the specified value.
104         * @param value the value.
105         */
106        public void setAll(Object value) {
107                for(int i = 0; i < array.length; i++)
108                        array[i] = value;
109        }
110        
111        public void swap(ResizingObjectArray other) {
112                Object[] arrayTmp = array;
113                int hintTmp = nextCapacityHint;
114                array = other.array;
115                nextCapacityHint = other.nextCapacityHint;
116                other.array = arrayTmp;
117                other.nextCapacityHint = hintTmp;
118        }
119        
120        
121}