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 }