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    }