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.0 (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      @GwtIncompatible("Array.newInstance(Class, int)")
043      public static <T> T[] newArray(Class<T> type, int length) {
044        return Platform.newArray(type, length);
045      }
046    
047      /**
048       * Returns a new array of the given length with the same type as a reference
049       * array.
050       *
051       * @param reference any array of the desired type
052       * @param length the length of the new array
053       */
054      public static <T> T[] newArray(T[] reference, int length) {
055        return Platform.newArray(reference, length);
056      }
057    
058      /**
059       * Returns a new array that contains the concatenated contents of two arrays.
060       *
061       * @param first the first array of elements to concatenate
062       * @param second the second array of elements to concatenate
063       * @param type the component type of the returned array
064       */
065      @GwtIncompatible("Array.newInstance(Class, int)")
066      public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
067        T[] result = newArray(type, first.length + second.length);
068        Platform.unsafeArrayCopy(first, 0, result, 0, first.length);
069        Platform.unsafeArrayCopy(second, 0, result, first.length, second.length);
070        return result;
071      }
072    
073      /**
074       * Returns a new array that prepends {@code element} to {@code array}.
075       *
076       * @param element the element to prepend to the front of {@code array}
077       * @param array the array of elements to append
078       * @return an array whose size is one larger than {@code array}, with
079       *     {@code element} occupying the first position, and the
080       *     elements of {@code array} occupying the remaining elements.
081       */
082      public static <T> T[] concat(@Nullable T element, T[] array) {
083        T[] result = newArray(array, array.length + 1);
084        result[0] = element;
085        Platform.unsafeArrayCopy(array, 0, result, 1, array.length);
086        return result;
087      }
088    
089      /**
090       * Returns a new array that appends {@code element} to {@code array}.
091       *
092       * @param array the array of elements to prepend
093       * @param element the element to append to the end
094       * @return an array whose size is one larger than {@code array}, with
095       *     the same contents as {@code array}, plus {@code element} occupying the
096       *     last position.
097       */
098      public static <T> T[] concat(T[] array, @Nullable T element) {
099        T[] result = arraysCopyOf(array, array.length + 1);
100        result[array.length] = element;
101        return result;
102      }
103    
104      /** GWT safe version of Arrays.copyOf. */
105      static <T> T[] arraysCopyOf(T[] original, int newLength) {
106        T[] copy = newArray(original, newLength);
107        Platform.unsafeArrayCopy(
108            original, 0, copy, 0, Math.min(original.length, newLength));
109        return copy;
110      }
111    
112      /**
113       * Returns an array containing all of the elements in the specified
114       * collection; the runtime type of the returned array is that of the specified
115       * array. If the collection fits in the specified array, it is returned
116       * therein. Otherwise, a new array is allocated with the runtime type of the
117       * specified array and the size of the specified collection.
118       *
119       * <p>If the collection fits in the specified array with room to spare (i.e.,
120       * the array has more elements than the collection), the element in the array
121       * immediately following the end of the collection is set to {@code null}.
122       * This is useful in determining the length of the collection <i>only</i> if
123       * the caller knows that the collection does not contain any null elements.
124       *
125       * <p>This method returns the elements in the order they are returned by the
126       * collection's iterator.
127       *
128       * <p>TODO(kevinb): support concurrently modified collections?
129       *
130       * @param c the collection for which to return an array of elements
131       * @param array the array in which to place the collection elements
132       * @throws ArrayStoreException if the runtime type of the specified array is
133       *     not a supertype of the runtime type of every element in the specified
134       *     collection
135       */
136      static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
137        int size = c.size();
138        if (array.length < size) {
139          array = newArray(array, size);
140        }
141        fillArray(c, array);
142        if (array.length > size) {
143          array[size] = null;
144        }
145        return array;
146      }
147    
148      /**
149       * Returns an array containing all of the elements in the specified
150       * collection. This method returns the elements in the order they are returned
151       * by the collection's iterator. The returned array is "safe" in that no
152       * references to it are maintained by the collection. The caller is thus free
153       * to modify the returned array.
154       *
155       * <p>This method assumes that the collection size doesn't change while the
156       * method is running.
157       *
158       * <p>TODO(kevinb): support concurrently modified collections?
159       *
160       * @param c the collection for which to return an array of elements
161       */
162      static Object[] toArrayImpl(Collection<?> c) {
163        return fillArray(c, new Object[c.size()]);
164      }
165    
166      private static Object[] fillArray(Iterable<?> elements, Object[] array) {
167        int i = 0;
168        for (Object element : elements) {
169          array[i++] = element;
170        }
171        return array;
172      }
173    
174      /**
175       * Swaps {@code array[i]} with {@code array[j]}.
176       */
177      static void swap(Object[] array, int i, int j) {
178        Object temp = array[i];
179        array[i] = array[j];
180        array[j] = temp;
181      }
182    }