001 /*
002 * Copyright (C) 2007 Google Inc.
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 (imported from Google Collections Library)
032 */
033 @GwtCompatible(emulated = true)
034 public final class ObjectArrays {
035 private ObjectArrays() {}
036
037 /**
038 * Returns a new array of the given length with the specified component type.
039 *
040 * @param type the component type
041 * @param length the length of the new array
042 */
043 @SuppressWarnings("unchecked")
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: Support concurrent collections whose size can change while the
130 * method is running.
131 *
132 * @param c the collection for which to return an array of elements
133 * @param array the array in which to place the collection elements
134 * @throws ArrayStoreException if the runtime type of the specified array is
135 * not a supertype of the runtime type of every element in the specified
136 * collection
137 */
138 static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
139 int size = c.size();
140 if (array.length < size) {
141 array = newArray(array, size);
142 }
143 fillArray(c, array);
144 if (array.length > size) {
145 array[size] = null;
146 }
147 return array;
148 }
149
150 /**
151 * Returns an array containing all of the elements in the specified
152 * collection. This method returns the elements in the order they are returned
153 * by the collection's iterator. The returned array is "safe" in that no
154 * references to it are maintained by the collection. The caller is thus free
155 * to modify the returned array.
156 *
157 * <p>This method assumes that the collection size doesn't change while the
158 * method is running.
159 *
160 * <p>TODO: Support concurrent collections whose size can change while the
161 * method is running.
162 *
163 * @param c the collection for which to return an array of elements
164 */
165 static Object[] toArrayImpl(Collection<?> c) {
166 return fillArray(c, new Object[c.size()]);
167 }
168
169 private static Object[] fillArray(Iterable<?> elements, Object[] array) {
170 int i = 0;
171 for (Object element : elements) {
172 array[i++] = element;
173 }
174 return array;
175 }
176 }