Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect;
     18 
     19 import static com.google.common.base.Preconditions.checkPositionIndexes;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 
     23 import java.util.Collection;
     24 
     25 import javax.annotation.Nullable;
     26 
     27 /**
     28  * Static utility methods pertaining to object arrays.
     29  *
     30  * @author Kevin Bourrillion
     31  * @since 2.0 (imported from Google Collections Library)
     32  */
     33 @GwtCompatible(emulated = true)
     34 public final class ObjectArrays {
     35   static final Object[] EMPTY_ARRAY = new Object[0];
     36 
     37   private ObjectArrays() {}
     38 
     39   /**
     40    * Returns a new array of the given length with the same type as a reference
     41    * array.
     42    *
     43    * @param reference any array of the desired type
     44    * @param length the length of the new array
     45    */
     46   public static <T> T[] newArray(T[] reference, int length) {
     47     return Platform.newArray(reference, length);
     48   }
     49 
     50   /**
     51    * Returns a new array that prepends {@code element} to {@code array}.
     52    *
     53    * @param element the element to prepend to the front of {@code array}
     54    * @param array the array of elements to append
     55    * @return an array whose size is one larger than {@code array}, with
     56    *     {@code element} occupying the first position, and the
     57    *     elements of {@code array} occupying the remaining elements.
     58    */
     59   public static <T> T[] concat(@Nullable T element, T[] array) {
     60     T[] result = newArray(array, array.length + 1);
     61     result[0] = element;
     62     System.arraycopy(array, 0, result, 1, array.length);
     63     return result;
     64   }
     65 
     66   /**
     67    * Returns a new array that appends {@code element} to {@code array}.
     68    *
     69    * @param array the array of elements to prepend
     70    * @param element the element to append to the end
     71    * @return an array whose size is one larger than {@code array}, with
     72    *     the same contents as {@code array}, plus {@code element} occupying the
     73    *     last position.
     74    */
     75   public static <T> T[] concat(T[] array, @Nullable T element) {
     76     T[] result = arraysCopyOf(array, array.length + 1);
     77     result[array.length] = element;
     78     return result;
     79   }
     80 
     81   /** GWT safe version of Arrays.copyOf. */
     82   static <T> T[] arraysCopyOf(T[] original, int newLength) {
     83     T[] copy = newArray(original, newLength);
     84     System.arraycopy(
     85         original, 0, copy, 0, Math.min(original.length, newLength));
     86     return copy;
     87   }
     88 
     89   /**
     90    * Returns an array containing all of the elements in the specified
     91    * collection; the runtime type of the returned array is that of the specified
     92    * array. If the collection fits in the specified array, it is returned
     93    * therein. Otherwise, a new array is allocated with the runtime type of the
     94    * specified array and the size of the specified collection.
     95    *
     96    * <p>If the collection fits in the specified array with room to spare (i.e.,
     97    * the array has more elements than the collection), the element in the array
     98    * immediately following the end of the collection is set to {@code null}.
     99    * This is useful in determining the length of the collection <i>only</i> if
    100    * the caller knows that the collection does not contain any null elements.
    101    *
    102    * <p>This method returns the elements in the order they are returned by the
    103    * collection's iterator.
    104    *
    105    * <p>TODO(kevinb): support concurrently modified collections?
    106    *
    107    * @param c the collection for which to return an array of elements
    108    * @param array the array in which to place the collection elements
    109    * @throws ArrayStoreException if the runtime type of the specified array is
    110    *     not a supertype of the runtime type of every element in the specified
    111    *     collection
    112    */
    113   static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
    114     int size = c.size();
    115     if (array.length < size) {
    116       array = newArray(array, size);
    117     }
    118     fillArray(c, array);
    119     if (array.length > size) {
    120       array[size] = null;
    121     }
    122     return array;
    123   }
    124 
    125   /**
    126    * Implementation of {@link Collection#toArray(Object[])} for collections backed by an object
    127    * array. the runtime type of the returned array is that of the specified array. If the collection
    128    * fits in the specified array, it is returned therein. Otherwise, a new array is allocated with
    129    * the runtime type of the specified array and the size of the specified collection.
    130    *
    131    * <p>If the collection fits in the specified array with room to spare (i.e., the array has more
    132    * elements than the collection), the element in the array immediately following the end of the
    133    * collection is set to {@code null}. This is useful in determining the length of the collection
    134    * <i>only</i> if the caller knows that the collection does not contain any null elements.
    135    */
    136   static <T> T[] toArrayImpl(Object[] src, int offset, int len, T[] dst) {
    137     checkPositionIndexes(offset, offset + len, src.length);
    138     if (dst.length < len) {
    139       dst = newArray(dst, len);
    140     } else if (dst.length > len) {
    141       dst[len] = null;
    142     }
    143     System.arraycopy(src, offset, dst, 0, len);
    144     return dst;
    145   }
    146 
    147   /**
    148    * Returns an array containing all of the elements in the specified
    149    * collection. This method returns the elements in the order they are returned
    150    * by the collection's iterator. The returned array is "safe" in that no
    151    * references to it are maintained by the collection. The caller is thus free
    152    * to modify the returned array.
    153    *
    154    * <p>This method assumes that the collection size doesn't change while the
    155    * method is running.
    156    *
    157    * <p>TODO(kevinb): support concurrently modified collections?
    158    *
    159    * @param c the collection for which to return an array of elements
    160    */
    161   static Object[] toArrayImpl(Collection<?> c) {
    162     return fillArray(c, new Object[c.size()]);
    163   }
    164 
    165   /**
    166    * Returns a copy of the specified subrange of the specified array that is literally an Object[],
    167    * and not e.g. a {@code String[]}.
    168    */
    169   static Object[] copyAsObjectArray(Object[] elements, int offset, int length) {
    170     checkPositionIndexes(offset, offset + length, elements.length);
    171     if (length == 0) {
    172       return EMPTY_ARRAY;
    173     }
    174     Object[] result = new Object[length];
    175     System.arraycopy(elements, offset, result, 0, length);
    176     return result;
    177   }
    178 
    179   private static Object[] fillArray(Iterable<?> elements, Object[] array) {
    180     int i = 0;
    181     for (Object element : elements) {
    182       array[i++] = element;
    183     }
    184     return array;
    185   }
    186 
    187   /**
    188    * Swaps {@code array[i]} with {@code array[j]}.
    189    */
    190   static void swap(Object[] array, int i, int j) {
    191     Object temp = array[i];
    192     array[i] = array[j];
    193     array[j] = temp;
    194   }
    195 
    196   static Object[] checkElementsNotNull(Object... array) {
    197     return checkElementsNotNull(array, array.length);
    198   }
    199 
    200   static Object[] checkElementsNotNull(Object[] array, int length) {
    201     for (int i = 0; i < length; i++) {
    202       checkElementNotNull(array[i], i);
    203     }
    204     return array;
    205   }
    206 
    207   // We do this instead of Preconditions.checkNotNull to save boxing and array
    208   // creation cost.
    209   static Object checkElementNotNull(Object element, int index) {
    210     if (element == null) {
    211       throw new NullPointerException("at index " + index);
    212     }
    213     return element;
    214   }
    215 }
    216 
    217