    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.lang.reflect.Array;
    023    import java.util.Collection;
    024
    025    import javax.annotation.Nullable;
    026
    027    /**
    028     * Static utility methods pertaining to object arrays.
    029     *
    030     * @author Kevin Bourrillion
    031     * @since 2.0 (imported from Google Collections Library)
    032     */
    033    @GwtCompatible(emulated = true)
    034    public final class ObjectArrays {
    035      static final Object[] EMPTY_ARRAY = new Object[0];
    036
    037      private ObjectArrays() {}
    038
    039      /**
    040       * Returns a new array of the given length with the specified component type.
    041       *
    042       * @param type the component type
    043       * @param length the length of the new array
    044       */
    045      @GwtIncompatible("Array.newInstance(Class, int)")
    046      @SuppressWarnings("unchecked")
    047      public static <T> T[] newArray(Class<T> type, int length) {
    048        return (T[]) Array.newInstance(type, length);
    049      }
    050
    051      /**
    052       * Returns a new array of the given length with the same type as a reference
    053       * array.
    054       *
    055       * @param reference any array of the desired type
    056       * @param length the length of the new array
    057       */
    058      public static <T> T[] newArray(T[] reference, int length) {
    059        return Platform.newArray(reference, length);
    060      }
    061
    062      /**
    063       * Returns a new array that contains the concatenated contents of two arrays.
    064       *
    065       * @param first the first array of elements to concatenate
    066       * @param second the second array of elements to concatenate
    067       * @param type the component type of the returned array
    068       */
    069      @GwtIncompatible("Array.newInstance(Class, int)")
    070      public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
    071        T[] result = newArray(type, first.length + second.length);
    072        System.arraycopy(first, 0, result, 0, first.length);
    073        System.arraycopy(second, 0, result, first.length, second.length);
    074        return result;
    075      }
    076
    077      /**
    078       * Returns a new array that prepends {@code element} to {@code array}.
    079       *
    080       * @param element the element to prepend to the front of {@code array}
    081       * @param array the array of elements to append
    082       * @return an array whose size is one larger than {@code array}, with
    083       *     {@code element} occupying the first position, and the
    084       *     elements of {@code array} occupying the remaining elements.
    085       */
    086      public static <T> T[] concat(@Nullable T element, T[] array) {
    087        T[] result = newArray(array, array.length + 1);
    088        result[0] = element;
    089        System.arraycopy(array, 0, result, 1, array.length);
    090        return result;
    091      }
    092
    093      /**
    094       * Returns a new array that appends {@code element} to {@code array}.
    095       *
    096       * @param array the array of elements to prepend
    097       * @param element the element to append to the end
    098       * @return an array whose size is one larger than {@code array}, with
    099       *     the same contents as {@code array}, plus {@code element} occupying the
    100       *     last position.
    101       */
    102      public static <T> T[] concat(T[] array, @Nullable T element) {
    103        T[] result = arraysCopyOf(array, array.length + 1);
    104        result[array.length] = element;
    105        return result;
    106      }
    107
    108      /** GWT safe version of Arrays.copyOf. */
    109      static <T> T[] arraysCopyOf(T[] original, int newLength) {
    110        T[] copy = newArray(original, newLength);
    111        System.arraycopy(
    112            original, 0, copy, 0, Math.min(original.length, newLength));
    113        return copy;
    114      }
    115
    116      /**
    117       * Returns an array containing all of the elements in the specified
    118       * collection; the runtime type of the returned array is that of the specified
    119       * array. If the collection fits in the specified array, it is returned
    120       * therein. Otherwise, a new array is allocated with the runtime type of the
    121       * specified array and the size of the specified collection.
    122       *
    123       * <p>If the collection fits in the specified array with room to spare (i.e.,
    124       * the array has more elements than the collection), the element in the array
    125       * immediately following the end of the collection is set to {@code null}.
    126       * This is useful in determining the length of the collection <i>only</i> if
    127       * the caller knows that the collection does not contain any null elements.
    128       *
    129       * <p>This method returns the elements in the order they are returned by the
    130       * collection's iterator.
    131       *
    132       * <p>TODO(kevinb): support concurrently modified collections?
    133       *
    134       * @param c the collection for which to return an array of elements
    135       * @param array the array in which to place the collection elements
    136       * @throws ArrayStoreException if the runtime type of the specified array is
    137       *     not a supertype of the runtime type of every element in the specified
    138       *     collection
    139       */
    140      static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
    141        int size = c.size();
    142        if (array.length < size) {
    143          array = newArray(array, size);
    144        }
    145        fillArray(c, array);
    146        if (array.length > size) {
    147          array[size] = null;
    148        }
    149        return array;
    150      }
    151
    152      /**
    153       * Returns an array containing all of the elements in the specified
    154       * collection. This method returns the elements in the order they are returned
    155       * by the collection's iterator. The returned array is "safe" in that no
    156       * references to it are maintained by the collection. The caller is thus free
    157       * to modify the returned array.
    158       *
    159       * <p>This method assumes that the collection size doesn't change while the
    160       * method is running.
    161       *
    162       * <p>TODO(kevinb): support concurrently modified collections?
    163       *
    164       * @param c the collection for which to return an array of elements
    165       */
    166      static Object[] toArrayImpl(Collection<?> c) {
    167        return fillArray(c, new Object[c.size()]);
    168      }
    169
    170      private static Object[] fillArray(Iterable<?> elements, Object[] array) {
    171        int i = 0;
    172        for (Object element : elements) {
    173          array[i++] = element;
    174        }
    175        return array;
    176      }
    177
    178      /**
    179       * Swaps {@code array[i]} with {@code array[j]}.
    180       */
    181      static void swap(Object[] array, int i, int j) {
    182        Object temp = array[i];
    183        array[i] = array[j];
    184        array[j] = temp;
    185      }
    186
    187      // We do this instead of Preconditions.checkNotNull to save boxing and array
    188      // creation cost.
    189      static Object checkElementNotNull(Object element, int index) {
    190        if (element == null) {
    191          throw new NullPointerException("at index " + index);
    192        }
    193        return element;
    194      }
    195    }