/*
 * Copyright (C) 2016 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.GwtCompatible;
import java.util.Comparator;
import java.util.function.Function;
import java.util.stream.Collector;

/**
 * Collectors utilities for {@code common.collect} internals.
 */
@GwtCompatible
final class CollectCollectors {
  static <T, K, V> Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap(
      Function<? super T, ? extends K> keyFunction,
      Function<? super T, ? extends V> valueFunction) {
    checkNotNull(keyFunction);
    checkNotNull(valueFunction);
    return Collector.of(
        ImmutableBiMap.Builder<K, V>::new,
        (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
        ImmutableBiMap.Builder::combine,
        ImmutableBiMap.Builder::build,
        new Collector.Characteristics[0]);
  }

  static <E> Collector<E, ?, ImmutableList<E>> toImmutableList() {
    return Collector.of(
        ImmutableList::<E>builder,
        ImmutableList.Builder::add,
        ImmutableList.Builder::combine,
        ImmutableList.Builder::build);
  }

  static <T, K, V> Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
      Function<? super T, ? extends K> keyFunction,
      Function<? super T, ? extends V> valueFunction) {
    checkNotNull(keyFunction);
    checkNotNull(valueFunction);
    return Collector.of(
        ImmutableMap.Builder<K, V>::new,
        (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
        ImmutableMap.Builder::combine,
        ImmutableMap.Builder::build);
  }

  static <E> Collector<E, ?, ImmutableSet<E>> toImmutableSet() {
    return Collector.of(
        ImmutableSet::<E>builder,
        ImmutableSet.Builder::add,
        ImmutableSet.Builder::combine,
        ImmutableSet.Builder::build);
  }

  static <T, K, V> Collector<T, ?, ImmutableSortedMap<K, V>> toImmutableSortedMap(
      Comparator<? super K> comparator,
      Function<? super T, ? extends K> keyFunction,
      Function<? super T, ? extends V> valueFunction) {
    checkNotNull(comparator);
    checkNotNull(keyFunction);
    checkNotNull(valueFunction);
    /*
     * We will always fail if there are duplicate keys, and the keys are always sorted by
     * the Comparator, so the entries can come in in arbitrary order -- so we report UNORDERED.
     */
    return Collector.of(
        () -> new ImmutableSortedMap.Builder<K, V>(comparator),
        (builder, input) -> builder.put(keyFunction.apply(input), valueFunction.apply(input)),
        ImmutableSortedMap.Builder::combine,
        ImmutableSortedMap.Builder::build,
        Collector.Characteristics.UNORDERED);
  }

  static <E> Collector<E, ?, ImmutableSortedSet<E>> toImmutableSortedSet(
      Comparator<? super E> comparator) {
    checkNotNull(comparator);
    return Collector.of(
        () -> new ImmutableSortedSet.Builder<E>(comparator),
        ImmutableSortedSet.Builder::add,
        ImmutableSortedSet.Builder::combine,
        ImmutableSortedSet.Builder::build);
  }
}


@@ -1503,34 +1503,44 @@
 0%5D);%0A  %7D%0A%0A  
+private 
 static 
-%3CE%3E
+final
  Collector%3CE
@@ -1530,33 +1530,38 @@
 final Collector%3C
-E
+Object
 , ?, ImmutableLi
@@ -1567,42 +1567,42 @@
 ist%3C
-E%3E%3E toImmutableList() %7B%0A    return
+Object%3E%3E TO_IMMUTABLE_LIST =%0A     
  Col
@@ -1604,32 +1604,34 @@
   Collector.of(%0A
+  
         Immutabl
@@ -1634,25 +1634,30 @@
 tableList::%3C
-E
+Object
 %3Ebuilder,%0A  
@@ -1654,32 +1654,34 @@
 uilder,%0A        
+ 
+ 
 ImmutableList.Bu
@@ -1684,32 +1684,34 @@
 t.Builder::add,%0A
+  
         Immutabl
@@ -1734,32 +1734,34 @@
 ombine,%0A        
+  
 ImmutableList.Bu
@@ -1766,32 +1766,142 @@
 Builder::build);
+%0A%0A  static %3CE%3E Collector%3CE, ?, ImmutableList%3CE%3E%3E toImmutableList() %7B%0A    return (Collector) TO_IMMUTABLE_LIST;
 %0A  %7D%0A%0A  static %3C
@@ -2371,37 +2371,49 @@
 build);%0A  %7D%0A
+  
 %0A  
+private 
 static 
-%3CE%3E
+final
  Collector%3CE
@@ -2403,33 +2403,38 @@
 final Collector%3C
-E
+Object
 , ?, ImmutableSe
@@ -2439,41 +2439,41 @@
 Set%3C
-E%3E%3E toImmutableSet() %7B%0A    return
+Object%3E%3E TO_IMMUTABLE_SET =%0A     
  Col
@@ -2475,32 +2475,34 @@
   Collector.of(%0A
+  
         Immutabl
@@ -2508,17 +2508,22 @@
 leSet::%3C
-E
+Object
 %3Ebuilder
@@ -2524,32 +2524,34 @@
 uilder,%0A        
+  
 ImmutableSet.Bui
@@ -2553,32 +2553,34 @@
 t.Builder::add,%0A
+  
         Immutabl
@@ -2594,32 +2594,34 @@
 ilder::combine,%0A
+  
         Immutabl
@@ -2637,24 +2637,131 @@
 der::build);
+%0A%0A  static %3CE%3E Collector%3CE, ?, ImmutableSet%3CE%3E%3E toImmutableSet() %7B%0A    return (Collector) TO_IMMUTABLE_SET;
 %0A  %7D%0A%0A  stat

Make toImmutableList() and toImmutableSet() collectors singletons.