001    /*
002     * Copyright (C) 2007 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import com.google.common.annotations.GwtCompatible;
020    import com.google.common.annotations.GwtIncompatible;
021    
022    import java.util.Collection;
023    
024    import javax.annotation.Nullable;
025    
026    /**
027     * Static utility methods pertaining to object arrays.
028     *
029     * @author Kevin Bourrillion
030     * @since 2 (imported from Google Collections Library)
031     */
032    @GwtCompatible(emulated = true)
033    public final class ObjectArrays {
034      private ObjectArrays() {}
035    
036      /**
037       * Returns a new array of the given length with the specified component type.
038       *
039       * @param type the component type
040       * @param length the length of the new array
041       */
042      @SuppressWarnings("unchecked")
043      @GwtIncompatible("Array.newInstance(Class, int)")
044      public static <T> T[] newArray(Class<T> type, int length) {
045        return Platform.newArray(type, length);
046      }
047    
048      /**
049       * Returns a new array of the given length with the same type as a reference
050       * array.
051       *
052       * @param reference any array of the desired type
053       * @param length the length of the new array
054       */
055      public static <T> T[] newArray(T[] reference, int length) {
056        return Platform.newArray(reference, length);
057      }
058    
059      /**
060       * Returns a new array that contains the concatenated contents of two arrays.
061       *
062       * @param first the first array of elements to concatenate
063       * @param second the second array of elements to concatenate
064       * @param type the component type of the returned array
065       */
066      @GwtIncompatible("Array.newInstance(Class, int)")
067      public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
068        T[] result = newArray(type, first.length + second.length);
069        Platform.unsafeArrayCopy(first, 0, result, 0, first.length);
070        Platform.unsafeArrayCopy(second, 0, result, first.length, second.length);
071        return result;
072      }
073    
074      /**
075       * Returns a new array that prepends {@code element} to {@code array}.
076       *
077       * @param element the element to prepend to the front of {@code array}
078       * @param array the array of elements to append
079       * @return an array whose size is one larger than {@code array}, with
080       *     {@code element} occupying the first position, and the
081       *     elements of {@code array} occupying the remaining elements.
082       */
083      public static <T> T[] concat(@Nullable T element, T[] array) {
084        T[] result = newArray(array, array.length + 1);
085        result[0] = element;
086        Platform.unsafeArrayCopy(array, 0, result, 1, array.length);
087        return result;
088      }
089    
090      /**
091       * Returns a new array that appends {@code element} to {@code array}.
092       *
093       * @param array the array of elements to prepend
094       * @param element the element to append to the end
095       * @return an array whose size is one larger than {@code array}, with
096       *     the same contents as {@code array}, plus {@code element} occupying the
097       *     last position.
098       */
099      public static <T> T[] concat(T[] array, @Nullable T element) {
100        T[] result = arraysCopyOf(array, array.length + 1);
101        result[array.length] = element;
102        return result;
103      }
104    
105      /** GWT safe version of Arrays.copyOf. */
106      private static <T> T[] arraysCopyOf(T[] original, int newLength) {
107        T[] copy = newArray(original, newLength);
108        Platform.unsafeArrayCopy(
109            original, 0, copy, 0, Math.min(original.length, newLength));
110        return copy;
111      }
112    
113      /**
114       * Returns an array containing all of the elements in the specified
115       * collection; the runtime type of the returned array is that of the specified
116       * array. If the collection fits in the specified array, it is returned
117       * therein. Otherwise, a new array is allocated with the runtime type of the
118       * specified array and the size of the specified collection.
119       *
120       * <p>If the collection fits in the specified array with room to spare (i.e.,
121       * the array has more elements than the collection), the element in the array
122       * immediately following the end of the collection is set to null. This is
123       * useful in determining the length of the collection <i>only</i> if the
124       * caller knows that the collection does not contain any null elements.
125       *
126       * <p>This method returns the elements in the order they are returned by the
127       * collection's iterator.
128       *
129       * <p>TODO(kevinb): support concurrently modified collections?
130       *
131       * @param c the collection for which to return an array of elements
132       * @param array the array in which to place the collection elements
133       * @throws ArrayStoreException if the runtime type of the specified array is
134       *     not a supertype of the runtime type of every element in the specified
135       *     collection
136       */
137      static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
138        int size = c.size();
139        if (array.length < size) {
140          array = newArray(array, size);
141        }
142        fillArray(c, array);
143        if (array.length > size) {
144          array[size] = null;
145        }
146        return array;
147      }
148    
149      /**
150       * Returns an array containing all of the elements in the specified
151       * collection. This method returns the elements in the order they are returned
152       * by the collection's iterator. The returned array is "safe" in that no
153       * references to it are maintained by the collection. The caller is thus free
154       * to modify the returned array.
155       *
156       * <p>This method assumes that the collection size doesn't change while the
157       * method is running.
158       *
159       * <p>TODO(kevinb): support concurrently modified collections?
160       *
161       * @param c the collection for which to return an array of elements
162       */
163      static Object[] toArrayImpl(Collection<?> c) {
164        return fillArray(c, new Object[c.size()]);
165      }
166    
167      private static Object[] fillArray(Iterable<?> elements, Object[] array) {
168        int i = 0;
169        for (Object element : elements) {
170          array[i++] = element;
171        }
172        return array;
173      }
174    
175      /**
176       * Swaps {@code array[i]} with {@code array[j]}.
177       */
178      static void swap(Object[] array, int i, int j) {
179        Object temp = array[i];
180        array[i] = array[j];
181        array[j] = temp;
182      }
183    }