    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    }