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