Coverage Summary for Class: CollectCollectors (com.google.common.collect)
| Class | Method, % | Line, % |
|---|---|---|
| CollectCollectors | 0% (0/50) | 0% (0/111) |
| CollectCollectors$EnumMapAccumulator | 0% (0/4) | 0% (0/13) |
| CollectCollectors$EnumSetAccumulator | 0% (0/5) | 0% (0/12) |
| Total | 0% (0/59) | 0% (0/136) |
1 /* 2 * Copyright (C) 2016 The Guava Authors 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 static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.common.annotations.Beta; 22 import com.google.common.annotations.GwtCompatible; 23 import com.google.common.annotations.GwtIncompatible; 24 import com.google.common.base.Preconditions; 25 import java.util.Collection; 26 import java.util.Comparator; 27 import java.util.EnumMap; 28 import java.util.EnumSet; 29 import java.util.LinkedHashMap; 30 import java.util.TreeMap; 31 import java.util.function.BinaryOperator; 32 import java.util.function.Function; 33 import java.util.function.Supplier; 34 import java.util.function.ToIntFunction; 35 import java.util.stream.Collector; 36 import java.util.stream.Collectors; 37 import java.util.stream.Stream; 38 import org.checkerframework.checker.nullness.qual.Nullable; 39 40 /** Collectors utilities for {@code common.collect} internals. */ 41 @GwtCompatible 42 final class CollectCollectors { 43 44 private static final Collector<Object, ?, ImmutableList<Object>> TO_IMMUTABLE_LIST = 45 Collector.of( 46 ImmutableList::builder, 47 ImmutableList.Builder::add, 48 ImmutableList.Builder::combine, 49 ImmutableList.Builder::build); 50 51 private static final Collector<Object, ?, ImmutableSet<Object>> TO_IMMUTABLE_SET = 52 Collector.of( 53 ImmutableSet::builder, 54 ImmutableSet.Builder::add, 55 ImmutableSet.Builder::combine, 56 ImmutableSet.Builder::build); 57 58 @GwtIncompatible 59 private static final Collector<Range<Comparable<?>>, ?, ImmutableRangeSet<Comparable<?>>> 60 TO_IMMUTABLE_RANGE_SET = 61 Collector.of( 62 ImmutableRangeSet::builder, 63 ImmutableRangeSet.Builder::add, 64 ImmutableRangeSet.Builder::combine, 65 ImmutableRangeSet.Builder::build); 66 67 // Lists 68 69 @SuppressWarnings({"rawtypes", "unchecked"}) 70 static <E> Collector<E, ?, ImmutableList<E>> toImmutableList() { 71 return (Collector) TO_IMMUTABLE_LIST; 72 } 73 74 // Sets 75 76 @SuppressWarnings({"rawtypes", "unchecked"}) 77 static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() { 78 return (Collector) TO_IMMUTABLE_SET; 79 } 80 81 static <E> Collector<E, ?, ImmutableSortedSet<E>> toImmutableSortedSet( 82 Comparator<? super E> comparator) { 83 checkNotNull(comparator); 84 return Collector.of( 85 () -> new ImmutableSortedSet.Builder<E>(comparator), 86 ImmutableSortedSet.Builder::add, 87 ImmutableSortedSet.Builder::combine, 88 ImmutableSortedSet.Builder::build); 89 } 90 91 @SuppressWarnings({"rawtypes", "unchecked"}) 92 static <E extends Enum<E>> Collector<E, ?, ImmutableSet<E>> toImmutableEnumSet() { 93 return (Collector) EnumSetAccumulator.TO_IMMUTABLE_ENUM_SET; 94 } 95 96 private static final class EnumSetAccumulator<E extends Enum<E>> { 97 @SuppressWarnings({"rawtypes", "unchecked"}) 98 static final Collector<Enum<?>, ?, ImmutableSet<? extends Enum<?>>> TO_IMMUTABLE_ENUM_SET = 99 (Collector) 100 Collector.<Enum, EnumSetAccumulator, ImmutableSet<?>>of( 101 EnumSetAccumulator::new, 102 EnumSetAccumulator::add, 103 EnumSetAccumulator::combine, 104 EnumSetAccumulator::toImmutableSet, 105 Collector.Characteristics.UNORDERED); 106 107 private @Nullable EnumSet<E> set; 108 109 void add(E e) { 110 if (set == null) { 111 set = EnumSet.of(e); 112 } else { 113 set.add(e); 114 } 115 } 116 117 EnumSetAccumulator<E> combine(EnumSetAccumulator<E> other) { 118 if (this.set == null) { 119 return other; 120 } else if (other.set == null) { 121 return this; 122 } else { 123 this.set.addAll(other.set); 124 return this; 125 } 126 } 127 128 ImmutableSet<E> toImmutableSet() { 129 return (set == null) ? ImmutableSet.<E>of() : ImmutableEnumSet.asImmutable(set); 130 } 131 } 132 133 @GwtIncompatible 134 @SuppressWarnings({"rawtypes", "unchecked"}) 135 static <E extends Comparable<? super E>> 136 Collector<Range<E>, ?, ImmutableRangeSet<E>> toImmutableRangeSet() { 137 return (Collector) TO_IMMUTABLE_RANGE_SET; 138 } 139 140 // Multisets 141 142 static <T, E> Collector<T, ?, ImmutableMultiset<E>> toImmutableMultiset( 143 Function<? super T, ? extends E> elementFunction, ToIntFunction<? super T> countFunction) { 144 checkNotNull(elementFunction); 145 checkNotNull(countFunction); 146 return Collector.of( 147 LinkedHashMultiset::create, 148 (multiset, t) -> 149 multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t)), 150 (multiset1, multiset2) -> { 151 multiset1.addAll(multiset2); 152 return multiset1; 153 }, 154 (Multiset<E> multiset) -> ImmutableMultiset.copyFromEntries(multiset.entrySet())); 155 } 156 157 static <T, E, M extends Multiset<E>> Collector<T, ?, M> toMultiset( 158 Function<? super T, E> elementFunction, 159 ToIntFunction<? super T> countFunction, 160 Supplier<M> multisetSupplier) { 161 checkNotNull(elementFunction); 162 checkNotNull(countFunction); 163 checkNotNull(multisetSupplier); 164 return Collector.of( 165 multisetSupplier, 166 (ms, t) -> ms.add(elementFunction.apply(t), countFunction.applyAsInt(t)), 167 (ms1, ms2) -> { 168 ms1.addAll(ms2); 169 return ms1; 170 }); 171 } 172 173 // Maps 174 175 static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 176 Function<? super T, ? extends K> keyFunction, 177 Function<? super T, ? extends V> valueFunction) { 178 checkNotNull(keyFunction); 179 checkNotNull(valueFunction); 180 return Collector.of( 181 ImmutableMap.Builder<K, V>::new, 182 (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), 183 ImmutableMap.Builder::combine, 184 ImmutableMap.Builder::build); 185 } 186 187 public static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap( 188 Function<? super T, ? extends K> keyFunction, 189 Function<? super T, ? extends V> valueFunction, 190 BinaryOperator<V> mergeFunction) { 191 checkNotNull(keyFunction); 192 checkNotNull(valueFunction); 193 checkNotNull(mergeFunction); 194 return Collectors.collectingAndThen( 195 Collectors.toMap(keyFunction, valueFunction, mergeFunction, LinkedHashMap::new), 196 ImmutableMap::copyOf); 197 } 198 199 static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap( 200 Comparator<? super K> comparator, 201 Function<? super T, ? extends K> keyFunction, 202 Function<? super T, ? extends V> valueFunction) { 203 checkNotNull(comparator); 204 checkNotNull(keyFunction); 205 checkNotNull(valueFunction); 206 /* 207 * We will always fail if there are duplicate keys, and the keys are always sorted by 208 * the Comparator, so the entries can come in an arbitrary order -- so we report UNORDERED. 209 */ 210 return Collector.of( 211 () -> new ImmutableSortedMap.Builder<K, V>(comparator), 212 (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), 213 ImmutableSortedMap.Builder::combine, 214 ImmutableSortedMap.Builder::build, 215 Collector.Characteristics.UNORDERED); 216 } 217 218 static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap( 219 Comparator<? super K> comparator, 220 Function<? super T, ? extends K> keyFunction, 221 Function<? super T, ? extends V> valueFunction, 222 BinaryOperator<V> mergeFunction) { 223 checkNotNull(comparator); 224 checkNotNull(keyFunction); 225 checkNotNull(valueFunction); 226 checkNotNull(mergeFunction); 227 return Collectors.collectingAndThen( 228 Collectors.toMap( 229 keyFunction, valueFunction, mergeFunction, () -> new TreeMap<K, V>(comparator)), 230 ImmutableSortedMap::copyOfSorted); 231 } 232 233 static <T, K, V> Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap( 234 Function<? super T, ? extends K> keyFunction, 235 Function<? super T, ? extends V> valueFunction) { 236 checkNotNull(keyFunction); 237 checkNotNull(valueFunction); 238 return Collector.of( 239 ImmutableBiMap.Builder<K, V>::new, 240 (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), 241 ImmutableBiMap.Builder::combine, 242 ImmutableBiMap.Builder::build, 243 new Collector.Characteristics[0]); 244 } 245 246 static <T, K extends Enum<K>, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableEnumMap( 247 Function<? super T, ? extends K> keyFunction, 248 Function<? super T, ? extends V> valueFunction) { 249 checkNotNull(keyFunction); 250 checkNotNull(valueFunction); 251 return Collector.of( 252 () -> 253 new EnumMapAccumulator<K, V>( 254 (v1, v2) -> { 255 throw new IllegalArgumentException("Multiple values for key: " + v1 + ", " + v2); 256 }), 257 (accum, t) -> { 258 K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t); 259 V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t); 260 accum.put(key, newValue); 261 }, 262 EnumMapAccumulator::combine, 263 EnumMapAccumulator::toImmutableMap, 264 Collector.Characteristics.UNORDERED); 265 } 266 267 static <T, K extends Enum<K>, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableEnumMap( 268 Function<? super T, ? extends K> keyFunction, 269 Function<? super T, ? extends V> valueFunction, 270 BinaryOperator<V> mergeFunction) { 271 checkNotNull(keyFunction); 272 checkNotNull(valueFunction); 273 checkNotNull(mergeFunction); 274 // not UNORDERED because we don't know if mergeFunction is commutative 275 return Collector.of( 276 () -> new EnumMapAccumulator<K, V>(mergeFunction), 277 (accum, t) -> { 278 K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t); 279 V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t); 280 accum.put(key, newValue); 281 }, 282 EnumMapAccumulator::combine, 283 EnumMapAccumulator::toImmutableMap); 284 } 285 286 private static class EnumMapAccumulator<K extends Enum<K>, V> { 287 private final BinaryOperator<V> mergeFunction; 288 private EnumMap<K, V> map = null; 289 290 EnumMapAccumulator(BinaryOperator<V> mergeFunction) { 291 this.mergeFunction = mergeFunction; 292 } 293 294 void put(K key, V value) { 295 if (map == null) { 296 map = new EnumMap<>(key.getDeclaringClass()); 297 } 298 map.merge(key, value, mergeFunction); 299 } 300 301 EnumMapAccumulator<K, V> combine(EnumMapAccumulator<K, V> other) { 302 if (this.map == null) { 303 return other; 304 } else if (other.map == null) { 305 return this; 306 } else { 307 other.map.forEach(this::put); 308 return this; 309 } 310 } 311 312 ImmutableMap<K, V> toImmutableMap() { 313 return (map == null) ? ImmutableMap.<K, V>of() : ImmutableEnumMap.asImmutable(map); 314 } 315 } 316 317 @GwtIncompatible 318 static <T, K extends Comparable<? super K>, V> 319 Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap( 320 Function<? super T, Range<K>> keyFunction, 321 Function<? super T, ? extends V> valueFunction) { 322 checkNotNull(keyFunction); 323 checkNotNull(valueFunction); 324 return Collector.of( 325 ImmutableRangeMap::<K, V>builder, 326 (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)), 327 ImmutableRangeMap.Builder::combine, 328 ImmutableRangeMap.Builder::build); 329 } 330 331 // Multimaps 332 333 static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> toImmutableListMultimap( 334 Function<? super T, ? extends K> keyFunction, 335 Function<? super T, ? extends V> valueFunction) { 336 checkNotNull(keyFunction, "keyFunction"); 337 checkNotNull(valueFunction, "valueFunction"); 338 return Collector.of( 339 ImmutableListMultimap::<K, V>builder, 340 (builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)), 341 ImmutableListMultimap.Builder::combine, 342 ImmutableListMultimap.Builder::build); 343 } 344 345 static <T, K, V> Collector<T, ?, ImmutableListMultimap<K, V>> flatteningToImmutableListMultimap( 346 Function<? super T, ? extends K> keyFunction, 347 Function<? super T, ? extends Stream<? extends V>> valuesFunction) { 348 checkNotNull(keyFunction); 349 checkNotNull(valuesFunction); 350 return Collectors.collectingAndThen( 351 flatteningToMultimap( 352 input -> checkNotNull(keyFunction.apply(input)), 353 input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull), 354 MultimapBuilder.linkedHashKeys().arrayListValues()::<K, V>build), 355 ImmutableListMultimap::copyOf); 356 } 357 358 static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> toImmutableSetMultimap( 359 Function<? super T, ? extends K> keyFunction, 360 Function<? super T, ? extends V> valueFunction) { 361 checkNotNull(keyFunction, "keyFunction"); 362 checkNotNull(valueFunction, "valueFunction"); 363 return Collector.of( 364 ImmutableSetMultimap::<K, V>builder, 365 (builder, t) -> builder.put(keyFunction.apply(t), valueFunction.apply(t)), 366 ImmutableSetMultimap.Builder::combine, 367 ImmutableSetMultimap.Builder::build); 368 } 369 370 static <T, K, V> Collector<T, ?, ImmutableSetMultimap<K, V>> flatteningToImmutableSetMultimap( 371 Function<? super T, ? extends K> keyFunction, 372 Function<? super T, ? extends Stream<? extends V>> valuesFunction) { 373 checkNotNull(keyFunction); 374 checkNotNull(valuesFunction); 375 return Collectors.collectingAndThen( 376 flatteningToMultimap( 377 input -> checkNotNull(keyFunction.apply(input)), 378 input -> valuesFunction.apply(input).peek(Preconditions::checkNotNull), 379 MultimapBuilder.linkedHashKeys().linkedHashSetValues()::<K, V>build), 380 ImmutableSetMultimap::copyOf); 381 } 382 383 static <T, K, V, M extends Multimap<K, V>> Collector<T, ?, M> toMultimap( 384 Function<? super T, ? extends K> keyFunction, 385 Function<? super T, ? extends V> valueFunction, 386 Supplier<M> multimapSupplier) { 387 checkNotNull(keyFunction); 388 checkNotNull(valueFunction); 389 checkNotNull(multimapSupplier); 390 return Collector.of( 391 multimapSupplier, 392 (multimap, input) -> multimap.put(keyFunction.apply(input), valueFunction.apply(input)), 393 (multimap1, multimap2) -> { 394 multimap1.putAll(multimap2); 395 return multimap1; 396 }); 397 } 398 399 @Beta 400 static <T, K, V, M extends Multimap<K, V>> Collector<T, ?, M> flatteningToMultimap( 401 Function<? super T, ? extends K> keyFunction, 402 Function<? super T, ? extends Stream<? extends V>> valueFunction, 403 Supplier<M> multimapSupplier) { 404 checkNotNull(keyFunction); 405 checkNotNull(valueFunction); 406 checkNotNull(multimapSupplier); 407 return Collector.of( 408 multimapSupplier, 409 (multimap, input) -> { 410 K key = keyFunction.apply(input); 411 Collection<V> valuesForKey = multimap.get(key); 412 valueFunction.apply(input).forEachOrdered(valuesForKey::add); 413 }, 414 (multimap1, multimap2) -> { 415 multimap1.putAll(multimap2); 416 return multimap1; 417 }); 418 } 419 }