001 /*
002 * Copyright (C) 2008 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 static com.google.common.base.Preconditions.checkArgument;
020 import static com.google.common.base.Preconditions.checkNotNull;
021
022 import com.google.common.annotations.GwtCompatible;
023 import com.google.common.base.Function;
024 import com.google.common.base.Joiner;
025 import com.google.common.base.Predicate;
026 import com.google.common.base.Predicates;
027 import com.google.common.primitives.Ints;
028
029 import java.util.AbstractCollection;
030 import java.util.ArrayList;
031 import java.util.Collection;
032 import java.util.Collections;
033 import java.util.Iterator;
034 import java.util.List;
035
036 /**
037 * Provides static methods for working with {@code Collection} instances.
038 *
039 * @author Chris Povirk
040 * @author Mike Bostock
041 * @author Jared Levy
042 * @since 2.0 (imported from Google Collections Library)
043 */
044 @GwtCompatible
045 public final class Collections2 {
046 private Collections2() {}
047
048 /**
049 * Returns the elements of {@code unfiltered} that satisfy a predicate. The
050 * returned collection is a live view of {@code unfiltered}; changes to one
051 * affect the other.
052 *
053 * <p>The resulting collection's iterator does not support {@code remove()},
054 * but all other collection methods are supported. When given an element that
055 * doesn't satisfy the predicate, the collection's {@code add()} and {@code
056 * addAll()} methods throw an {@link IllegalArgumentException}. When methods
057 * such as {@code removeAll()} and {@code clear()} are called on the filtered
058 * collection, only elements that satisfy the filter will be removed from the
059 * underlying collection.
060 *
061 * <p>The returned collection isn't threadsafe or serializable, even if
062 * {@code unfiltered} is.
063 *
064 * <p>Many of the filtered collection's methods, such as {@code size()},
065 * iterate across every element in the underlying collection and determine
066 * which elements satisfy the filter. When a live view is <i>not</i> needed,
067 * it may be faster to copy {@code Iterables.filter(unfiltered, predicate)}
068 * and use the copy.
069 *
070 * <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>,
071 * as documented at {@link Predicate#apply}. Do not provide a predicate such
072 * as {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent
073 * with equals. (See {@link Iterables#filter(Iterable, Class)} for related
074 * functionality.)
075 */
076 // TODO(kevinb): how can we omit that Iterables link when building gwt
077 // javadoc?
078 public static <E> Collection<E> filter(
079 Collection<E> unfiltered, Predicate<? super E> predicate) {
080 if (unfiltered instanceof FilteredCollection) {
081 // Support clear(), removeAll(), and retainAll() when filtering a filtered
082 // collection.
083 return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
084 }
085
086 return new FilteredCollection<E>(
087 checkNotNull(unfiltered), checkNotNull(predicate));
088 }
089
090 /**
091 * Delegates to {@link Collection#contains}. Returns {@code false} if the
092 * {@code contains} method throws a {@code ClassCastException}.
093 */
094 static boolean safeContains(Collection<?> collection, Object object) {
095 try {
096 return collection.contains(object);
097 } catch (ClassCastException e) {
098 return false;
099 }
100 }
101
102 static class FilteredCollection<E> implements Collection<E> {
103 final Collection<E> unfiltered;
104 final Predicate<? super E> predicate;
105
106 FilteredCollection(Collection<E> unfiltered,
107 Predicate<? super E> predicate) {
108 this.unfiltered = unfiltered;
109 this.predicate = predicate;
110 }
111
112 FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
113 return new FilteredCollection<E>(unfiltered,
114 Predicates.<E>and(predicate, newPredicate));
115 // .<E> above needed to compile in JDK 5
116 }
117
118 @Override
119 public boolean add(E element) {
120 checkArgument(predicate.apply(element));
121 return unfiltered.add(element);
122 }
123
124 @Override
125 public boolean addAll(Collection<? extends E> collection) {
126 for (E element : collection) {
127 checkArgument(predicate.apply(element));
128 }
129 return unfiltered.addAll(collection);
130 }
131
132 @Override
133 public void clear() {
134 Iterables.removeIf(unfiltered, predicate);
135 }
136
137 @Override
138 public boolean contains(Object element) {
139 try {
140 // unsafe cast can result in a CCE from predicate.apply(), which we
141 // will catch
142 @SuppressWarnings("unchecked")
143 E e = (E) element;
144
145 /*
146 * We check whether e satisfies the predicate, when we really mean to
147 * check whether the element contained in the set does. This is ok as
148 * long as the predicate is consistent with equals, as required.
149 */
150 return predicate.apply(e) && unfiltered.contains(element);
151 } catch (NullPointerException e) {
152 return false;
153 } catch (ClassCastException e) {
154 return false;
155 }
156 }
157
158 @Override
159 public boolean containsAll(Collection<?> collection) {
160 for (Object element : collection) {
161 if (!contains(element)) {
162 return false;
163 }
164 }
165 return true;
166 }
167
168 @Override
169 public boolean isEmpty() {
170 return !Iterators.any(unfiltered.iterator(), predicate);
171 }
172
173 @Override
174 public Iterator<E> iterator() {
175 return Iterators.filter(unfiltered.iterator(), predicate);
176 }
177
178 @Override
179 public boolean remove(Object element) {
180 try {
181 // unsafe cast can result in a CCE from predicate.apply(), which we
182 // will catch
183 @SuppressWarnings("unchecked")
184 E e = (E) element;
185
186 // See comment in contains() concerning predicate.apply(e)
187 return predicate.apply(e) && unfiltered.remove(element);
188 } catch (NullPointerException e) {
189 return false;
190 } catch (ClassCastException e) {
191 return false;
192 }
193 }
194
195 @Override
196 public boolean removeAll(final Collection<?> collection) {
197 checkNotNull(collection);
198 Predicate<E> combinedPredicate = new Predicate<E>() {
199 @Override
200 public boolean apply(E input) {
201 return predicate.apply(input) && collection.contains(input);
202 }
203 };
204 return Iterables.removeIf(unfiltered, combinedPredicate);
205 }
206
207 @Override
208 public boolean retainAll(final Collection<?> collection) {
209 checkNotNull(collection);
210 Predicate<E> combinedPredicate = new Predicate<E>() {
211 @Override
212 public boolean apply(E input) {
213 // See comment in contains() concerning predicate.apply(e)
214 return predicate.apply(input) && !collection.contains(input);
215 }
216 };
217 return Iterables.removeIf(unfiltered, combinedPredicate);
218 }
219
220 @Override
221 public int size() {
222 return Iterators.size(iterator());
223 }
224
225 @Override
226 public Object[] toArray() {
227 // creating an ArrayList so filtering happens once
228 return Lists.newArrayList(iterator()).toArray();
229 }
230
231 @Override
232 public <T> T[] toArray(T[] array) {
233 return Lists.newArrayList(iterator()).toArray(array);
234 }
235
236 @Override public String toString() {
237 return Iterators.toString(iterator());
238 }
239 }
240
241 /**
242 * Returns a collection that applies {@code function} to each element of
243 * {@code fromCollection}. The returned collection is a live view of {@code
244 * fromCollection}; changes to one affect the other.
245 *
246 * <p>The returned collection's {@code add()} and {@code addAll()} methods
247 * throw an {@link UnsupportedOperationException}. All other collection
248 * methods are supported, as long as {@code fromCollection} supports them.
249 *
250 * <p>The returned collection isn't threadsafe or serializable, even if
251 * {@code fromCollection} is.
252 *
253 * <p>When a live view is <i>not</i> needed, it may be faster to copy the
254 * transformed collection and use the copy.
255 *
256 * <p>If the input {@code Collection} is known to be a {@code List}, consider
257 * {@link Lists#transform}. If only an {@code Iterable} is available, use
258 * {@link Iterables#transform}.
259 */
260 public static <F, T> Collection<T> transform(Collection<F> fromCollection,
261 Function<? super F, T> function) {
262 return new TransformedCollection<F, T>(fromCollection, function);
263 }
264
265 static class TransformedCollection<F, T> extends AbstractCollection<T> {
266 final Collection<F> fromCollection;
267 final Function<? super F, ? extends T> function;
268
269 TransformedCollection(Collection<F> fromCollection,
270 Function<? super F, ? extends T> function) {
271 this.fromCollection = checkNotNull(fromCollection);
272 this.function = checkNotNull(function);
273 }
274
275 @Override public void clear() {
276 fromCollection.clear();
277 }
278
279 @Override public boolean isEmpty() {
280 return fromCollection.isEmpty();
281 }
282
283 @Override public Iterator<T> iterator() {
284 return Iterators.transform(fromCollection.iterator(), function);
285 }
286
287 @Override public int size() {
288 return fromCollection.size();
289 }
290 }
291
292 /**
293 * Returns {@code true} if the collection {@code self} contains all of the
294 * elements in the collection {@code c}.
295 *
296 * <p>This method iterates over the specified collection {@code c}, checking
297 * each element returned by the iterator in turn to see if it is contained in
298 * the specified collection {@code self}. If all elements are so contained,
299 * {@code true} is returned, otherwise {@code false}.
300 *
301 * @param self a collection which might contain all elements in {@code c}
302 * @param c a collection whose elements might be contained by {@code self}
303 */
304 static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
305 checkNotNull(self);
306 for (Object o : c) {
307 if (!self.contains(o)) {
308 return false;
309 }
310 }
311 return true;
312 }
313
314 /**
315 * An implementation of {@link Collection#toString()}.
316 */
317 static String toStringImpl(final Collection<?> collection) {
318 StringBuilder sb
319 = newStringBuilderForCollection(collection.size()).append('[');
320 STANDARD_JOINER.appendTo(
321 sb, Iterables.transform(collection, new Function<Object, Object>() {
322 @Override public Object apply(Object input) {
323 return input == collection ? "(this Collection)" : input;
324 }
325 }));
326 return sb.append(']').toString();
327 }
328
329 /**
330 * Returns best-effort-sized StringBuilder based on the given collection size.
331 */
332 static StringBuilder newStringBuilderForCollection(int size) {
333 checkArgument(size >= 0, "size must be non-negative");
334 return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
335 }
336
337 /**
338 * Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
339 */
340 static <T> Collection<T> cast(Iterable<T> iterable) {
341 return (Collection<T>) iterable;
342 }
343
344 static final Joiner STANDARD_JOINER = Joiner.on(", ");
345
346 // TODO(user): Maybe move the mathematical methods to a separate
347 // package-permission class.
348 }