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