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