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 }