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 }