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 }