• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.base.Function;
21 import com.google.common.base.Joiner;
22 import com.google.common.base.Predicate;
23 import com.google.common.base.Predicates;
24 
25 import java.util.AbstractCollection;
26 import java.util.Collection;
27 import java.util.Iterator;
28 import java.util.Set;
29 
30 import javax.annotation.Nullable;
31 
32 import static com.google.common.base.Preconditions.checkArgument;
33 import static com.google.common.base.Preconditions.checkNotNull;
34 
35 /**
36  * Provides static methods for working with {@code Collection} instances.
37  *
38  * @author Chris Povirk
39  * @author Mike Bostock
40  * @author Jared Levy
41  * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
42  */
43 @GwtCompatible
44 public final class Collections2 {
Collections2()45   private Collections2() {}
46 
47   /**
48    * Returns {@code true} if the collection {@code self} contains all of the
49    * elements in the collection {@code c}.
50    *
51    * <p>This method iterates over the specified collection {@code c}, checking
52    * each element returned by the iterator in turn to see if it is contained in
53    * the specified collection {@code self}. If all elements are so contained,
54    * {@code true} is returned, otherwise {@code false}.
55    *
56    * @param self a collection which might contain all elements in {@code c}
57    * @param c a collection whose elements might be contained by {@code self}
58    */
59   // TODO: Make public?
containsAll(Collection<?> self, Collection<?> c)60   static boolean containsAll(Collection<?> self, Collection<?> c) {
61     checkNotNull(self);
62     for (Object o : c) {
63       if (!self.contains(o)) {
64         return false;
65       }
66     }
67     return true;
68   }
69 
70   /**
71    * Converts an iterable into a collection. If the iterable is already a
72    * collection, it is returned. Otherwise, an {@link java.util.ArrayList} is
73    * created with the contents of the iterable in the same iteration order.
74    */
toCollection(Iterable<E> iterable)75   static <E> Collection<E> toCollection(Iterable<E> iterable) {
76     return (iterable instanceof Collection)
77         ? (Collection<E>) iterable : Lists.newArrayList(iterable);
78   }
79 
80   /**
81    * Returns the elements of {@code unfiltered} that satisfy a predicate. The
82    * returned collection is a live view of {@code unfiltered}; changes to one
83    * affect the other.
84    *
85    * <p>The resulting collection's iterator does not support {@code remove()},
86    * but all other collection methods are supported. The collection's
87    * {@code add()} and {@code addAll()} methods throw an
88    * {@link IllegalArgumentException} if an element that doesn't satisfy the
89    * predicate is provided. When methods such as {@code removeAll()} and
90    * {@code clear()} are called on the filtered collection, only elements that
91    * satisfy the filter will be removed from the underlying collection.
92    *
93    * <p>The returned collection isn't threadsafe or serializable, even if
94    * {@code unfiltered} is.
95    *
96    * <p>Many of the filtered collection's methods, such as {@code size()},
97    * iterate across every element in the underlying collection and determine
98    * which elements satisfy the filter. When a live view is <i>not</i> needed,
99    * it may be faster to copy {@code Iterables.filter(unfiltered, predicate)}
100    * and use the copy.
101    */
filter( Collection<E> unfiltered, Predicate<? super E> predicate)102   public static <E> Collection<E> filter(
103       Collection<E> unfiltered, Predicate<? super E> predicate) {
104     if (unfiltered instanceof FilteredCollection) {
105       // Support clear(), removeAll(), and retainAll() when filtering a filtered
106       // collection.
107       return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
108     }
109 
110     return new FilteredCollection<E>(
111         checkNotNull(unfiltered), checkNotNull(predicate));
112   }
113 
114   /**
115    * Delegates to {@link Collection#contains}.  Returns {@code false} on {@code
116    * ClassCastException}
117    */
safeContains(Collection<?> collection, Object object)118   static boolean safeContains(Collection<?> collection, Object object) {
119     try {
120       return collection.contains(object);
121     } catch (ClassCastException e) {
122       return false;
123     }
124   }
125 
126   static class FilteredCollection<E> implements Collection<E> {
127     final Collection<E> unfiltered;
128     final Predicate<? super E> predicate;
129 
FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate)130     FilteredCollection(Collection<E> unfiltered,
131         Predicate<? super E> predicate) {
132       this.unfiltered = unfiltered;
133       this.predicate = predicate;
134     }
135 
createCombined(Predicate<? super E> newPredicate)136     FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
137       return new FilteredCollection<E>(unfiltered,
138           Predicates.<E>and(predicate, newPredicate));
139       // .<E> above needed to compile in JDK 5
140     }
141 
add(E element)142     public boolean add(E element) {
143       checkArgument(predicate.apply(element));
144       return unfiltered.add(element);
145     }
146 
addAll(Collection<? extends E> collection)147     public boolean addAll(Collection<? extends E> collection) {
148       for (E element : collection) {
149         checkArgument(predicate.apply(element));
150       }
151       return unfiltered.addAll(collection);
152     }
153 
clear()154     public void clear() {
155       Iterables.removeIf(unfiltered, predicate);
156     }
157 
contains(Object element)158     public boolean contains(Object element) {
159       try {
160         // unsafe cast can result in a CCE from predicate.apply(), which we
161         // will catch
162         @SuppressWarnings("unchecked")
163         E e = (E) element;
164         return predicate.apply(e) && unfiltered.contains(element);
165       } catch (NullPointerException e) {
166         return false;
167       } catch (ClassCastException e) {
168         return false;
169       }
170     }
171 
containsAll(Collection<?> collection)172     public boolean containsAll(Collection<?> collection) {
173       for (Object element : collection) {
174         if (!contains(element)) {
175           return false;
176         }
177       }
178       return true;
179     }
180 
isEmpty()181     public boolean isEmpty() {
182       return !Iterators.any(unfiltered.iterator(), predicate);
183     }
184 
iterator()185     public Iterator<E> iterator() {
186       return Iterators.filter(unfiltered.iterator(), predicate);
187     }
188 
remove(Object element)189     public boolean remove(Object element) {
190       try {
191         // unsafe cast can result in a CCE from predicate.apply(), which we
192         // will catch
193         @SuppressWarnings("unchecked")
194         E e = (E) element;
195         return predicate.apply(e) && unfiltered.remove(element);
196       } catch (NullPointerException e) {
197         return false;
198       } catch (ClassCastException e) {
199         return false;
200       }
201     }
202 
removeAll(final Collection<?> collection)203     public boolean removeAll(final Collection<?> collection) {
204       checkNotNull(collection);
205       Predicate<E> combinedPredicate = new Predicate<E>() {
206         public boolean apply(E input) {
207           return predicate.apply(input) && collection.contains(input);
208         }
209       };
210       return Iterables.removeIf(unfiltered, combinedPredicate);
211     }
212 
retainAll(final Collection<?> collection)213     public boolean retainAll(final Collection<?> collection) {
214       checkNotNull(collection);
215       Predicate<E> combinedPredicate = new Predicate<E>() {
216         public boolean apply(E input) {
217           return predicate.apply(input) && !collection.contains(input);
218         }
219       };
220       return Iterables.removeIf(unfiltered, combinedPredicate);
221     }
222 
size()223     public int size() {
224       return Iterators.size(iterator());
225     }
226 
toArray()227     public Object[] toArray() {
228       // creating an ArrayList so filtering happens once
229       return Lists.newArrayList(iterator()).toArray();
230     }
231 
toArray(T[] array)232     public <T> T[] toArray(T[] array) {
233       return Lists.newArrayList(iterator()).toArray(array);
234     }
235 
toString()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    */
transform(Collection<F> fromCollection, Function<? super F, T> function)256   public static <F, T> Collection<T> transform(Collection<F> fromCollection,
257       Function<? super F, T> function) {
258     return new TransformedCollection<F, T>(fromCollection, function);
259   }
260 
261   static class TransformedCollection<F, T> extends AbstractCollection<T> {
262     final Collection<F> fromCollection;
263     final Function<? super F, ? extends T> function;
264 
TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function)265     TransformedCollection(Collection<F> fromCollection,
266         Function<? super F, ? extends T> function) {
267       this.fromCollection = checkNotNull(fromCollection);
268       this.function = checkNotNull(function);
269     }
270 
clear()271     @Override public void clear() {
272       fromCollection.clear();
273     }
274 
isEmpty()275     @Override public boolean isEmpty() {
276       return fromCollection.isEmpty();
277     }
278 
iterator()279     @Override public Iterator<T> iterator() {
280       return Iterators.transform(fromCollection.iterator(), function);
281     }
282 
size()283     @Override public int size() {
284       return fromCollection.size();
285     }
286   }
287 
setEquals(Set<?> thisSet, @Nullable Object object)288   static boolean setEquals(Set<?> thisSet, @Nullable Object object) {
289     if (object == thisSet) {
290       return true;
291     }
292     if (object instanceof Set) {
293       Set<?> thatSet = (Set<?>) object;
294       return thisSet.size() == thatSet.size()
295           && thisSet.containsAll(thatSet);
296     }
297     return false;
298   }
299 
300   static final Joiner standardJoiner = Joiner.on(", ");
301 }
302