/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.util; import java.lang.reflect.Array; /** * The ArrayResizer provides methods that allow to modify the size of a given * array after its construction. An ArrayResizer is especially useful with * regard to dynamic structures based on arrays, because this class supports * methods to expanded or shrink an array depending on user specified * parameters. * * <p>Therefore the user has to consider these two kinds of sizes of an array: * <ul> * <li><b>logical size</b>: a user specified size that represents the minimum * needed size of the array after the resize-operation.</li> * <li><b>physical size</b>: the actual returned size of a given array after a * resize-operation.</li> * </ul> * An instance of ArrayResizer can be created with the parameters * <code>fmin</code>, <code>fover</code>, <code>funder</code>, which refer to * these two sizes of an array.</p> * * <p><b>IMPORTANT:</b> These parameters have to be specified with a value in * a range of [0,1]! (per cent values) * <ul> * <li><code><b>fmin</b></code> is the minimal utilization of capacity * concerning the ratio between logical and physical size after an * expansion or contraction of an array. The following condition is valid: * <pre>logical size * fmin <= physical size * fmin <= logical size</pre> * <ul> * <li><b>expansion:</b> * <pre> * fmin = 0: logical size = physical size * fover * fmin = 1: logical size = physical size * </pre></li> * <li><b>contraction:</b> * <pre> * fmin = 0: logical size = physical size * funder * fmin = 1: logical size = physical size * </pre></li> * </ul></li> * <li><code><b>fover</b></code> is a parameter specifying the array's logical * size in proportion to the array's physical size after an expansion. * <pre> * fover = 0: logical size = fmin * physical size * fover = 1: logical size = physical size * </pre></li> * <li><code><b>funder</b></code> is a parameter specifying the array's logical * size in proportion to the array's physical size after a contraction. * <pre> * funder = 0: logical size = fmin * physical size * funder = 1: logical size = physical size * </pre></li> * </ul> * To resize a given (Object or primitive type) array, one of the * resize-methods of this class has to be called. Therefore the array to be * resized and the minimum <code>size</code> (logical size) the array should * have afer a contraction or an expanison has to be specified. Depending on * this parameter <code>size</code> (logical size) and the array's length the * given array is expanded, i.e. the method <code>grow(array, size)</code> is * called, or shrinked, i.e.<code>shrink(array, size)</code> is called.</p> * * <p><b>Note</b>, that the specified parameter <code>size</code> represents * the minimum size (logical size) an array can have after a resize-operation. * The actual physical size after a resize-operation is determined by the * parameters <code>fover</code> (grow-operation) and <code>funder</code> * (shrink-operation) in the following way: * <ul> * <li><tt>grow: returned size = (int)(size / (fover+(1-fover)*fmin))</tt></li> * <li><tt>shrink: returned size = (int) (size / (funder+(1-funder)*fmin))</tt></li> * </ul> * So the following <b>invariant conditions</b> are still valid: * <ul> * <li><b>grow</b>: * <pre> * logical size * fmin <= physical size * fmin <= logical size * logical size * fover <= physical size * fover <= logical size * </pre></li> * <li><b>shrink</b>: * <pre> * logical size * fmin <= physical size * fmin <= logical size * logical size * funder <= physical size * funder <= logical size * </pre></li> * </ul></p> * * <p>Further this class provides some useful methods to copy arrays and * contains a static field DEFAULT_INSTANCE, which is similar to the design * pattern, named Singleton except that there are no mechanisms to avoid the * creation of other instances. <b>Intent:</b> <quote>"Ensure a class only has * one instance, and provide a global point of access to it."</quote> For * further information see: "Gamma et al.: <i>DesignPatterns</i>. Addision * Wesley 1998."</p> * * <p><b>Example usage (1):</b> * <code><pre> * ArrayResizer arrayResizer = ArrayResizer.DEFAULT_INSTANCE; // get a default instance * int[] ints = new int[10]; // use a primitive type array * int size = 20; // minimal needed size (logical size) --> grow * int[] resizedArray = (int[])arrayResizer.resize(ints, size); // resize-call * </code></pre> * This examples creates a new default instance of this class and calls the * <code>resize</code> method for a primitive type (int) array. By using a * default instance of this class, the fields <code>fmin</code>, * <code>fover</code>, <code>funder</code> are initialized with '0.5'. The * logical size is set to '20'. The initial array size is '10' so the * ArrayResizer calls <code>grow(ints, 20)</code>. So the returned size, i.e. * the physical size, is '26', because * <pre> * (grow: return (int)(size / (fover+(1-fover)*fmin)) * ==> (int)(20/(0.5+(1-0.5)*0.5) = 26 * </pre></p> * * <p><b>Example usage (2):</b> * <code><pre> * arrayResizer = new ArrayResizer(0.2); // create new ArrayResizer with fmin = 0.2 * ints = new int[100]; // use a primitive type array * size = 10; // minimal needed size (logical size) --> shrink * resizedArray = (int[])arrayResizer.resize(ints, size); // resize-call * </code></pre> * In this case a new instance of ArrayResizer is created by specifying * <code>fmin</code> with value '0.2'. The other fields <code>fover</code> and * <code>fmin</code> are set to '0.5'. Because the array has an initial array * size of '100' and the logical size is specified with '10' the array has to * be shrinked. Therefore the <code>resize</code> method calls * <code>shrink(ints, 10)</code>. Because of <code>fmin</code> the physical * array size has to be 20 per cent larger (or even more) than the logical * array size. So the actual physical size is determined by: * <pre> * (shrink: return (int)(size / (funder+(1-funder)*fmin)) * </pre> * So the returned physical size is '16'.</p> * * <p><b>Example usage (3):</b> * <code><pre> * System.out.println("------------------EXAMPLE 3-------------------"); * // create new ArrayResizer with fmin = 0.2, fover = 0.6 and funder = 0.8 * arrayResizer = new ArrayResizer(0.2, 0.6, 0.8); * // use an Object array * Integer[] objects = new Integer[]{new Integer(0), new Integer(1), new Integer(2)}; * size = 10; // minimal needed size (logical size) --> grow * Integer[] resizedObjectArray = (Integer[])arrayResizer.resize(objects, size); // resize-call * System.out.println("initial array size:" +objects.length); * System.out.println("logical size: " +size); * System.out.println("physical size: " +resizedObjectArray.length +" (returned size!)"); * System.out.println("fover: " +arrayResizer.fover); * System.out.println("funder: " +arrayResizer.funder); * System.out.println("fmin: " +arrayResizer.fmin); * System.out.println("logical size * fover: " +size*arrayResizer.fover); * System.out.println("logical size * funder: " +size*arrayResizer.funder); * System.out.println("logical size * fmin: " +size*arrayResizer.fmin); * System.out.println("physical size * fover: " +resizedArray.length*arrayResizer.fover); * System.out.println("physical size * funder: " +resizedArray.length*arrayResizer.funder); * System.out.println("physical size * fmin: " +(int)(resizedObjectArray.length*arrayResizer.fmin)); * System.out.println("NOTE the following conditions:"); * System.out.println("general: logical size * fmin <= physical size * fmin <= logical size"); * System.out.println("grow-operation: logical size * fover <= physical size * fover <= logical size"); * System.out.println("shrink-operation: logical size * funder <= physical size * funder <= logical size"); * System.out.println(); * </code></pre> * This last example demonstrates the most complex constructor that can be used * to create an an instance of ArrayResizer. Further it demonstrates the usage * of Object-type arrays concerning the <code>resize</code> method. The initial * array size is '3', therefore an expansion has to be made to gain a minimum * logical size of '10'. Further the output shows the used sizes, the used * parameters and their relations, i.e. the invariant conditions.</p> * * <p>Every example shown above generates an output like example (3) if you run * the use cases.</p> * * @see java.lang.reflect.Array * @see java.lang.System#arraycopy(Object,int,Object,int,int) * @see xxl.core.collections.queues.ArrayQueue * @see xxl.core.collections.queues.DynamicHeap */ public class ArrayResizer { /** * <code>fmin</code> is the minimal utilization of capacity concerning the * ratio between logical and physical size after an expansion or * contraction of an array. The following condition is valid: * logical size * fmin <= physical size * fmin <= logical size * <ul> * <li><b>expansion:</b><br> * <pre> * fmin = 0: logical size = physical size * fover * fmin = 1: logical size = physical size * </pre></li> * <li><b>contraction:</b><br> * <pre> * fmin = 0: logical size = physical size * funder * fmin = 1: logical size = physical size * </pre></li> * </ul> */ protected double fmin; // minimaler Fuellgrad /** * <code>fover</code> is a parameter specifying the array's logical size in * proportion to the array's physical size after an expansion. * <pre> * fover = 0: logical size = fmin * physical size * fover = 1: logical size = physical size * </pre> */ protected double fover; /** * <code>funder</code> is a parameter specifying the array's logical size * in proportion to the array's physical size after a contraction. * <pre> * funder = 0: logical size = fmin * physical size * funder = 1: logical size = physical size * </pre> */ protected double funder; /** * This instance can be used for getting a default instance of * ArrayResizer. It is similar to the <i>Singleton Design Pattern</i> (for * further details see Creational Patterns, Singleton in <i>Design * Patterns: Elements of Reusable Object-Oriented Software</i> by Erich * Gamma, Richard Helm, Ralph Johnson, and John Vlissides) except that * there are no mechanisms to avoid the creation of other instances of * ArrayResizer. */ public static final ArrayResizer DEFAULT_INSTANCE = new ArrayResizer(); /** * Creates a new ArrayResizer using a default value of * <code>fmin = 0.5</code>. */ public ArrayResizer() { this(0.5); } /** * Creates a new ArrayResizer using default values of * <code>fover = funder = 0.5</code>. * * @param fmin is the minimal utilization of capacity concerning the ratio * between logical and physical size after an expansion or * contraction of an array. * <ul> * <li><b>expansion:</b> * <pre> * fmin = 0: logical size = physical size * fover * fmin = 1: logical size = physical size * </pre></li> * <li><b>contraction:</b> * <pre> * fmin = 0: logical size = physical size * funder * fmin = 1: logical size = physical size * </pre></li> * </ul> */ public ArrayResizer(double fmin) { this(fmin, 0.5, 0.5); } /** * Creates a new ArrayResizer by initializing <code>fover</code> and * <code>funder</code> with the same given value <code>f</code>. * * @param fmin is the minimal utilization of capacity concerning the ratio * between logical and physical size after an expansion or * contraction of an array. * <ul> * <li><b>expansion:</b> * <pre> * fmin = 0: logical size = physical size * fover * fmin = 1: logical size = physical size * </pre></li> * <li><b>contraction:</b> * <pre> * fmin = 0: logical size = physical size * funder * fmin = 1: logical size = physical size * </pre></li> * </ul> * @param f parameter specifying the array's logical size in proportion to * the array's physical size after an expansion or contraction. * Thats means <code>fover</code> and <code>funder</code> are * initialized with the same value <code>f</code>. */ public ArrayResizer(double fmin, double f) { this(fmin, f, f); } /** * Creates a new ArrayResizer. * * @param fmin is the minimal utilization of capacity concerning the ratio * between logical and physical size after an expansion or * contraction of an array. * <ul> * <li><b>expansion:</b> * <pre> * fmin = 0: logical size = physical size * fover * fmin = 1: logical size = physical size * </pre></li> * <li><b>contraction:</b> * <pre> * fmin = 0: logical size = physical size * funder * fmin = 1: logical size = physical size * </pre></li> * </ul> * @param fover a parameter specifying the array's logical size in * proportion to the array's physical size after an expansion. * <pre> * fover = 0: logical size = fmin * physical size * fover = 1: logical size = physical size * </pre> * @param funder a parameter specifying the array's logical size in * proportion to the array's physical size after a contraction. * <pre> * funder = 0: logical size = fmin * physical size * funder = 1: logical size = physical size * </pre> */ public ArrayResizer(double fmin, double fover, double funder) { this.fmin = fmin; this.fover = fover; this.funder = funder; } /** * Returns a new array with a minimum size of <code>size</code> after the * expansion. This parameter <code>size</code> is the logical size computed * with. Creates a new array with the specified component type and a new * physical size that is computed by: * <code><pre> * (int)(size/(fover+(1-fover)*fmin)) * </pre></code> * <b>Note</b>, that <code>fover</code> is a parameter specifying the * array's logical size in proportion to the array's physical size after an * expansion. When <code>fover = 0 </code> then an array is created with a * new physical size of <code>size / fmin</code>, i.e. * <code>logical size = fmin * physical size</code>. When * <code>fover = 1</code> then an array is created were the logical size is * equal to the physical size. To guarantee the <b>invariant conditions</b> * <pre> * logical size * fmin <= physical size * fmin <= logical size * logical size * fover <= physical size * fover <= logical size * </pre> * the parameter <code>size</code> has not only to be divided by * <code>fover</code> but by the complement of <code>fover</code> * multiplied by <code>fmin</code>. * * <p>Creates a new instance of an array by calling * {@link java.lang.reflect.Array#newInstance(Class, int)}.</p> * * @param array the array to be expanded. * @param size the minimal needed size of the array after an expansion * (logical size). * @return a new array with a physical size computed by * <code>(int)(size/(fover+(1-fover)*fmin))</code>. * @throws NullPointerException if the specified <code>array</code> * parameter is null. * @throws NegativeArraySizeException if the specified <code>length</code> * is negative. */ public Object grow(Object array, int size) { return Array.newInstance(array.getClass().getComponentType(), (int)(size/(fover+(1-fover)*fmin))); } /** * Returns a new array with a minimum size of <code>size</code> after the * contraction. This parameter <code>size</code> is the logical size * computed with. Creates a new array with the specified component type and * a new physical size that is computed by: * <code><pre> * (int)(size/(funder+(1-funder)*fmin)) * </code></pre> * <b>Note</b>, that <code>funder</code> is a parameter specifying the * array's logical size in proportion to the array's physical size after a * contraction. When <code>funder = 0 </code> then an array is created with * a new physical size of <code>size / fmin</code>, i.e. * <code>logical size = fmin * physical size</code>. When * <code>funder = 1</code> then an array is created were the logical size * is equal to the physical size. To guarantee the * <b>invariant conditions</b> * <pre> * logical size * fmin <= physical size * fmin <= logical size * logical size * funder <= physical size * funder <= logical size * </pre> * the parameter size has not only to be divided by <code>funder</code> but * by the complement of <code>funder</code> multiplied by * <code>fmin</code>. * * <p>Creates a new instance of an array by calling * {@link java.lang.reflect.Array#newInstance(Class, int)}.</p> * * @param array the array to be shrinked. * @param size the minimal needed size of the array after a contraction * (logical size). * @return a new array with a physical size computed by * <code>(int)(size/(funder+(1-funder)*fmin))</code>. * @throws NullPointerException if the specified * <code>array</code> parameter is null. * @throws NegativeArraySizeException if the specified <code>length</code> * is negative. */ public Object shrink(Object array, int size) { return Array.newInstance(array.getClass().getComponentType(), (int)(size/(funder+(1-funder)*fmin))); } /** * Copies an array from the specified source array, beginning at the * specified position, to the specified position of the destination array. * A subsequence of array components are copied from the source array * referenced by <code>source</code> to the destination array referenced by * <code>target</code>. The number of components copied is equal to the * <code>size</code> argument. The components at positions * <code>sourceOffset</code> through <code>sourceOffset+size-1</code> in * the source array are copied into positions <code>targetOffset</code> * through <code>targetOffset+size-1</code>, respectively, of the * destination array. * * <p>If the <code>source</code> and <code>target</code> arguments refer to * the same array object, then the copying is performed as if the * components at positions <code>sourceOffset</code> through * <code>sourceOffset+size-1</code> were first copied to a temporary array * with <code>size</code> components and then the contents of the temporary * array were copied into positions <code>targetOffset</code> through * <code>targetOffset+size-1</code> of the destination array.</p> * * <p>If <code>target</code> is <code>null</code>, then a * <code>NullPointerException</code> is thrown.</p> * * <p>If <code>source</code> is <code>null</code>, then a * <code>NullPointerException</code> is thrown and the destination array is * not modified.</p> * * <p>Otherwise, if any of the following is true, an * <code>ArrayStoreException</code> is thrown and the destination is not * modified: * <ul> * <li>The <code>source</code> argument refers to an object that is not an * array.</li> * <li>The <code>target</code> argument refers to an object that is not an * array.</li> * <li>The <code>source</code> argument and <code>target</code> argument * refer to arrays whose component types are different primitive types. * </li> * <li>The <code>source</code> argument refers to an array with a primitive * component type and the <code>target</code> argument refers to an * array with a reference component type.</li> * <li>The <code>source</code> argument refers to an array with a reference * component type and the <code>target</code> argument refers to an * array with a primitive component type.</li> * </ul> * Otherwise, if any of the following is true, an * <code>IndexOutOfBoundsException</code> is thrown and the destination is * not modified: * <ul> * <li>The <code>sourceOffset</code> argument is negative.</li> * <li>The <code>targetOffset</code> argument is negative.</li> * <li>The <code>size</code> argument is negative.</li> * <li><code>sourceOffset+size</code> is greater than * <code>source.length</code>, the length of the source array.</li> * <li><code>targetOffset+size</code> is greater than * <code>target.length</code>, the length of the destination array. * </li> * </ul> * Otherwise, if any actual component of the source array from position * <code>sourceOffset</code> through <code>sourceOffset+size-1</code> * cannot be converted to the component type of the destination array by * assignment conversion, an <code>ArrayStoreException</code> is thrown. In * this case, let <b><i>k</i></b> be the smallest nonnegative integer less * than length such that * <code>source[sourceOffset+</code><i>k</i><code>]</code> cannot be * converted to the component type of the destination array; when the * exception is thrown, source array components from positions * <code>sourceOffset</code> through * <code>sourceOffset+</code><i>k</i><code>-1</code> will already have been * copied to destination array positions <code>targetOffset</code> through * <code>targetOffset+</code><i>k</I><code>-1</code> and no other positions * of the destination array will have been modified. (Because of the * restrictions already itemized, this paragraph effectively applies only * to the situation where both arrays have component types that are * reference types.)</p> * * <p>This method calls * {@link java.lang.System#arraycopy(Object,int,Object,int,int)}.</p> * * @param source the source array. * @param from start position in the source array. * @param target the destination array. * @param to start position in the destination data. * @param size the number of array elements to be copied. * @throws IndexOutOfBoundsException if copying would cause access of data * outside array bounds. * @throws ArrayStoreException if an element in the <code>source</code> * array could not be stored into the <code>target</code> array * because of a type mismatch. * @throws NullPointerException if either <code>source</code> or * <code>target</code> is <code>null</code>. */ public static void copy(Object source, int from, Object target, int to, int size) { int sourceLength = Array.getLength(source), targetLength = Array.getLength(target), length; for (; size>0; size -= length) { length = Math.min(Math.min(sourceLength-from, targetLength-to), size); System.arraycopy(source, from, target, to, length); from = (from+length)%sourceLength; to = (to+length)%targetLength; } } /** * Copies an array from the specified source array at position 0 to * position 0 of the destination array. The number of components copied is * equal to the <code>size</code> argument. The components at positions * <code>sourceOffset</code> through <code>sourceOffset+length-1</code> in * the source array are copied into positions <code>targetOffset</code> * through <code>targetOffset+length-1</code>, respectively, of the * destination array. * * <p>If the <code>source</code> and <code>target</code> arguments refer to * the same array object, then the copying is performed as if the * components at positions <code>0</code> through <code>size-1</code> were * first copied to a temporary array with <code>size</code> components and * then the contents of the temporary array were copied into positions * <code>0</code> through <code>size-1</code> of the destination array.</p> * * <p>If <code>target</code> is <code>null</code>, then a * <code>NullPointerException</code> is thrown.</p> * * <p>If <code>source</code> is <code>null</code>, then a * <code>NullPointerException</code> is thrown and the destination array is * not modified.</p> * * <p>Otherwise, if any of the following is true, an * <code>ArrayStoreException</code> is thrown and the destination is not * modified: * <ul> * <li>The <code>source</code> argument refers to an object that is not an * array.</li> * <li>The <code>target</code> argument refers to an object that is not an * array.</li> * <li>The <code>source</code> argument and <code>target</code> argument * refer to arrays whose component types are different primitive types. * </li> * <li>The <code>source</code> argument refers to an array with a primitive * component type and the <code>target</code> argument refers to an * array with a reference component type.</li> * <li>The <code>source</code> argument refers to an array with a reference * component type and the <code>target</code> argument refers to an * array with a primitive component type.</li> * </ul> * Otherwise, if any of the following is true, an * <code>IndexOutOfBoundsException</code> is thrown and the destination is * not modified: * <ul> * <li>The <code>size</code> argument is negative.</li> * </ul> * Otherwise, if any actual component of the source array from position * <code>0</code> through <code>size-1</code> cannot be converted to the * component type of the destination array by assignment conversion, an * <code>ArrayStoreException</code> is thrown. In this case, let * <b><i>k</i></b> be the smallest nonnegative integer less than length * such that <code>source[</code><i>k</i><code>]</code> cannot be converted * to the component type of the destination array; when the exception is * thrown, source array components from positions <code>0</code> through * <code></code><i>k</i><code>-1</code> will already have been copied to * destination array positions <code>0</code> through * <code></code><i>k</I><code>-1</code> and no other positions of the * destination array will have been modified. (Because of the restrictions * already itemized, this paragraph effectively applies only to the * situation where both arrays have component types that are reference * types.)</p> * * <p>This method calls: * <code><pre> * copy(source, 0, target, 0, size); * </pre></code> * * @param source the source array. * @param target the destination array. * @param size the number of array elements to be copied. * @throws IndexOutOfBoundsException if copying would cause access of data * outside array bounds. * @throws ArrayStoreException if an element in the <code>source</code> * array could not be stored into the <code>target</code> array * because of a type mismatch. * @throws NullPointerException if either <code>source</code> or * <code>target</code> is <code>null</code>. * @see #copy(Object, int, Object, int, int) */ public void copy(Object source, Object target, int size) { copy(source, 0, target, 0, size); } /** * Resizes a given (Object or primitive type) array. The minimum * <code>size</code> (logical size) the array should have afer a * contraction or an expanison has to be specified. Depending on this * logical size and the array's length the given array is expanded, i.e. * <code>grow(array, size)</code> is called, or shrinked, i.e. * <code>shrink(array, size)</code> is called. * * @param array the array to be resized. * @param size the minimal needed size of the array (logical size). * @return the resized array is returned. * @throws ArrayStoreException if an element in the <code>source</code> * array could not be stored into the <code>target</code> array * because of a type mismatch. * @throws NullPointerException if the given array is <code>null</code>. * @throws IllegalArgumentException if the given object argument is not an * array. * @see #grow(Object,int) * @see #shrink(Object,int) */ public Object resize(Object array, int size) { int length = Array.getLength(array); if (size>length) { Object newArray = grow(array, size); copy(array, newArray, length); array = newArray; } else if (size<Math.ceil(fmin*length)) { Object newArray = shrink(array, size); copy(array, newArray, size); array = newArray; } return array; } /** * Resizes a given Object-array. (no primitive types allowed) The minimum * <code>size</code> (logical size) the array should have afer a * contraction or an expanison has to be specified. Depending on this * logical size and the array's length the given array is expanded, i.e. * <code>grow(array, size)</code> is called, or shrinked, i.e. * <code>shrink(array, size)</code> is called. * * @param <T> the component type of the array to be resized. * @param array the Object-array to resized. * @param size the minimal needed size of the array (logical size). * @return the resized array is returned. * @throws ArrayStoreException if an element in the <code>source</code> * array could not be stored into the <code>target</code> array * because of a type mismatch. * @throws NullPointerException if the given array is <code>null</code>. * @throws IllegalArgumentException if the given object argument is not an * array. * @see #grow(Object,int) * @see #shrink(Object,int) */ @SuppressWarnings("unchecked") // array of correct component type is created by using reflection public <T> T[] resize(T[] array, int size) { if (size > array.length) { Object newArray = grow(array, size); copy(array, newArray, array.length); array = (T[])newArray; } else if (size < Math.ceil(fmin*array.length)) { Object newArray = shrink(array, size); copy(array, newArray, size); array = (T[])newArray; } return array; } }