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 }