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
017package com.google.common.collect;
018
019import static com.google.common.collect.CollectPreconditions.checkEntryNotNull;
020import static com.google.common.collect.CollectPreconditions.checkNonnegative;
021
022import com.google.common.annotations.GwtCompatible;
023import com.google.common.annotations.J2ktIncompatible;
024import com.google.errorprone.annotations.CanIgnoreReturnValue;
025import com.google.errorprone.annotations.DoNotCall;
026import java.io.InvalidObjectException;
027import java.io.ObjectInputStream;
028import java.util.Arrays;
029import java.util.Collection;
030import java.util.Comparator;
031import java.util.Map;
032import java.util.function.BinaryOperator;
033import java.util.function.Function;
034import java.util.stream.Collector;
035import java.util.stream.Collectors;
036import javax.annotation.CheckForNull;
037import org.checkerframework.checker.nullness.qual.Nullable;
038
039/**
040 * A {@link BiMap} whose contents will never change, with many other important properties detailed
041 * at {@link ImmutableCollection}.
042 *
043 * @author Jared Levy
044 * @since 2.0
045 */
046@GwtCompatible(serializable = true, emulated = true)
047public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {
048
049  /**
050   * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose keys
051   * and values are the result of applying the provided mapping functions to the input elements.
052   * Entries appear in the result {@code ImmutableBiMap} in encounter order.
053   *
054   * <p>If the mapped keys or values contain duplicates (according to {@link
055   * Object#equals(Object)}), an {@code IllegalArgumentException} is thrown when the collection
056   * operation is performed. (This differs from the {@code Collector} returned by {@link
057   * Collectors#toMap(Function, Function)}, which throws an {@code IllegalStateException}.)
058   *
059   * @since 33.2.0 (available since 21.0 in guava-jre)
060   */
061  @SuppressWarnings("Java7ApiChecker")
062  @IgnoreJRERequirement // Users will use this only if they're already using streams.
063  public static <T extends @Nullable Object, K, V>
064      Collector<T, ?, ImmutableBiMap<K, V>> toImmutableBiMap(
065          Function<? super T, ? extends K> keyFunction,
066          Function<? super T, ? extends V> valueFunction) {
067    return CollectCollectors.toImmutableBiMap(keyFunction, valueFunction);
068  }
069
070  /**
071   * Returns the empty bimap.
072   *
073   * <p><b>Performance note:</b> the instance returned is a singleton.
074   */
075  // Casting to any type is safe because the set will never hold any elements.
076  @SuppressWarnings("unchecked")
077  public static <K, V> ImmutableBiMap<K, V> of() {
078    return (ImmutableBiMap<K, V>) RegularImmutableBiMap.EMPTY;
079  }
080
081  /** Returns an immutable bimap containing a single entry. */
082  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
083    checkEntryNotNull(k1, v1);
084    return new RegularImmutableBiMap<>(new Object[] {k1, v1}, 1);
085  }
086
087  /**
088   * Returns an immutable map containing the given entries, in order.
089   *
090   * @throws IllegalArgumentException if duplicate keys or values are added
091   */
092  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
093    checkEntryNotNull(k1, v1);
094    checkEntryNotNull(k2, v2);
095    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2}, 2);
096  }
097
098  /**
099   * Returns an immutable map containing the given entries, in order.
100   *
101   * @throws IllegalArgumentException if duplicate keys or values are added
102   */
103  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
104    checkEntryNotNull(k1, v1);
105    checkEntryNotNull(k2, v2);
106    checkEntryNotNull(k3, v3);
107    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3}, 3);
108  }
109
110  /**
111   * Returns an immutable map containing the given entries, in order.
112   *
113   * @throws IllegalArgumentException if duplicate keys or values are added
114   */
115  public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
116    checkEntryNotNull(k1, v1);
117    checkEntryNotNull(k2, v2);
118    checkEntryNotNull(k3, v3);
119    checkEntryNotNull(k4, v4);
120    return new RegularImmutableBiMap<K, V>(new Object[] {k1, v1, k2, v2, k3, v3, k4, v4}, 4);
121  }
122
123  /**
124   * Returns an immutable map containing the given entries, in order.
125   *
126   * @throws IllegalArgumentException if duplicate keys or values are added
127   */
128  public static <K, V> ImmutableBiMap<K, V> of(
129      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
130    checkEntryNotNull(k1, v1);
131    checkEntryNotNull(k2, v2);
132    checkEntryNotNull(k3, v3);
133    checkEntryNotNull(k4, v4);
134    checkEntryNotNull(k5, v5);
135    return new RegularImmutableBiMap<K, V>(
136        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5}, 5);
137  }
138
139  /**
140   * Returns an immutable map containing the given entries, in order.
141   *
142   * @throws IllegalArgumentException if duplicate keys or values are added
143   * @since 31.0
144   */
145  public static <K, V> ImmutableBiMap<K, V> of(
146      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
147    checkEntryNotNull(k1, v1);
148    checkEntryNotNull(k2, v2);
149    checkEntryNotNull(k3, v3);
150    checkEntryNotNull(k4, v4);
151    checkEntryNotNull(k5, v5);
152    checkEntryNotNull(k6, v6);
153    return new RegularImmutableBiMap<K, V>(
154        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6}, 6);
155  }
156  /**
157   * Returns an immutable map containing the given entries, in order.
158   *
159   * @throws IllegalArgumentException if duplicate keys or values are added
160   * @since 31.0
161   */
162  public static <K, V> ImmutableBiMap<K, V> of(
163      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
164    checkEntryNotNull(k1, v1);
165    checkEntryNotNull(k2, v2);
166    checkEntryNotNull(k3, v3);
167    checkEntryNotNull(k4, v4);
168    checkEntryNotNull(k5, v5);
169    checkEntryNotNull(k6, v6);
170    checkEntryNotNull(k7, v7);
171    return new RegularImmutableBiMap<K, V>(
172        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7}, 7);
173  }
174  /**
175   * Returns an immutable map containing the given entries, in order.
176   *
177   * @throws IllegalArgumentException if duplicate keys or values are added
178   * @since 31.0
179   */
180  public static <K, V> ImmutableBiMap<K, V> of(
181      K k1,
182      V v1,
183      K k2,
184      V v2,
185      K k3,
186      V v3,
187      K k4,
188      V v4,
189      K k5,
190      V v5,
191      K k6,
192      V v6,
193      K k7,
194      V v7,
195      K k8,
196      V v8) {
197    checkEntryNotNull(k1, v1);
198    checkEntryNotNull(k2, v2);
199    checkEntryNotNull(k3, v3);
200    checkEntryNotNull(k4, v4);
201    checkEntryNotNull(k5, v5);
202    checkEntryNotNull(k6, v6);
203    checkEntryNotNull(k7, v7);
204    checkEntryNotNull(k8, v8);
205    return new RegularImmutableBiMap<K, V>(
206        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8}, 8);
207  }
208  /**
209   * Returns an immutable map containing the given entries, in order.
210   *
211   * @throws IllegalArgumentException if duplicate keys or values are added
212   * @since 31.0
213   */
214  public static <K, V> ImmutableBiMap<K, V> of(
215      K k1,
216      V v1,
217      K k2,
218      V v2,
219      K k3,
220      V v3,
221      K k4,
222      V v4,
223      K k5,
224      V v5,
225      K k6,
226      V v6,
227      K k7,
228      V v7,
229      K k8,
230      V v8,
231      K k9,
232      V v9) {
233    checkEntryNotNull(k1, v1);
234    checkEntryNotNull(k2, v2);
235    checkEntryNotNull(k3, v3);
236    checkEntryNotNull(k4, v4);
237    checkEntryNotNull(k5, v5);
238    checkEntryNotNull(k6, v6);
239    checkEntryNotNull(k7, v7);
240    checkEntryNotNull(k8, v8);
241    checkEntryNotNull(k9, v9);
242    return new RegularImmutableBiMap<K, V>(
243        new Object[] {k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9}, 9);
244  }
245  /**
246   * Returns an immutable map containing the given entries, in order.
247   *
248   * @throws IllegalArgumentException if duplicate keys or values are added
249   * @since 31.0
250   */
251  public static <K, V> ImmutableBiMap<K, V> of(
252      K k1,
253      V v1,
254      K k2,
255      V v2,
256      K k3,
257      V v3,
258      K k4,
259      V v4,
260      K k5,
261      V v5,
262      K k6,
263      V v6,
264      K k7,
265      V v7,
266      K k8,
267      V v8,
268      K k9,
269      V v9,
270      K k10,
271      V v10) {
272    checkEntryNotNull(k1, v1);
273    checkEntryNotNull(k2, v2);
274    checkEntryNotNull(k3, v3);
275    checkEntryNotNull(k4, v4);
276    checkEntryNotNull(k5, v5);
277    checkEntryNotNull(k6, v6);
278    checkEntryNotNull(k7, v7);
279    checkEntryNotNull(k8, v8);
280    checkEntryNotNull(k9, v9);
281    checkEntryNotNull(k10, v10);
282    return new RegularImmutableBiMap<K, V>(
283        new Object[] {
284          k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10
285        },
286        10);
287  }
288
289  // looking for of() with > 10 entries? Use the builder or ofEntries instead.
290
291  /**
292   * Returns an immutable map containing the given entries, in order.
293   *
294   * @throws IllegalArgumentException if duplicate keys or values are provided
295   * @since 31.0
296   */
297  @SafeVarargs
298  public static <K, V> ImmutableBiMap<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
299    @SuppressWarnings("unchecked") // we will only ever read these
300    Entry<K, V>[] entries2 = (Entry<K, V>[]) entries;
301    return copyOf(Arrays.asList(entries2));
302  }
303
304  /**
305   * Returns a new builder. The generated builder is equivalent to the builder created by the {@link
306   * Builder} constructor.
307   */
308  public static <K, V> Builder<K, V> builder() {
309    return new Builder<>();
310  }
311
312  /**
313   * Returns a new builder, expecting the specified number of entries to be added.
314   *
315   * <p>If {@code expectedSize} is exactly the number of entries added to the builder before {@link
316   * Builder#build} is called, the builder is likely to perform better than an unsized {@link
317   * #builder()} would have.
318   *
319   * <p>It is not specified if any performance benefits apply if {@code expectedSize} is close to,
320   * but not exactly, the number of entries added to the builder.
321   *
322   * @since 23.1
323   */
324  public static <K, V> Builder<K, V> builderWithExpectedSize(int expectedSize) {
325    checkNonnegative(expectedSize, "expectedSize");
326    return new Builder<>(expectedSize);
327  }
328
329  /**
330   * A builder for creating immutable bimap instances, especially {@code public static final} bimaps
331   * ("constant bimaps"). Example:
332   *
333   * <pre>{@code
334   * static final ImmutableBiMap<String, Integer> WORD_TO_INT =
335   *     new ImmutableBiMap.Builder<String, Integer>()
336   *         .put("one", 1)
337   *         .put("two", 2)
338   *         .put("three", 3)
339   *         .buildOrThrow();
340   * }</pre>
341   *
342   * <p>For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods are even more
343   * convenient.
344   *
345   * <p>By default, a {@code Builder} will generate bimaps that iterate over entries in the order
346   * they were inserted into the builder. For example, in the above example, {@code
347   * WORD_TO_INT.entrySet()} is guaranteed to iterate over the entries in the order {@code "one"=1,
348   * "two"=2, "three"=3}, and {@code keySet()} and {@code values()} respect the same order. If you
349   * want a different order, consider using {@link #orderEntriesByValue(Comparator)}, which changes
350   * this builder to sort entries by value.
351   *
352   * <p>Builder instances can be reused - it is safe to call {@link #buildOrThrow} multiple times to
353   * build multiple bimaps in series. Each bimap is a superset of the bimaps created before it.
354   *
355   * @since 2.0
356   */
357  public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
358    /**
359     * Creates a new builder. The returned builder is equivalent to the builder generated by {@link
360     * ImmutableBiMap#builder}.
361     */
362    public Builder() {
363      super();
364    }
365
366    Builder(int size) {
367      super(size);
368    }
369
370    /**
371     * Associates {@code key} with {@code value} in the built bimap. Duplicate keys or values are
372     * not allowed, and will cause {@link #build} to fail.
373     */
374    @CanIgnoreReturnValue
375    @Override
376    public Builder<K, V> put(K key, V value) {
377      super.put(key, value);
378      return this;
379    }
380
381    /**
382     * Adds the given {@code entry} to the bimap. Duplicate keys or values are not allowed, and will
383     * cause {@link #build} to fail.
384     *
385     * @since 19.0
386     */
387    @CanIgnoreReturnValue
388    @Override
389    public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
390      super.put(entry);
391      return this;
392    }
393
394    /**
395     * Associates all of the given map's keys and values in the built bimap. Duplicate keys or
396     * values are not allowed, and will cause {@link #build} to fail.
397     *
398     * @throws NullPointerException if any key or value in {@code map} is null
399     */
400    @CanIgnoreReturnValue
401    @Override
402    public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
403      super.putAll(map);
404      return this;
405    }
406
407    /**
408     * Adds all of the given entries to the built bimap. Duplicate keys or values are not allowed,
409     * and will cause {@link #build} to fail.
410     *
411     * @throws NullPointerException if any key, value, or entry is null
412     * @since 19.0
413     */
414    @CanIgnoreReturnValue
415    @Override
416    public Builder<K, V> putAll(Iterable<? extends Entry<? extends K, ? extends V>> entries) {
417      super.putAll(entries);
418      return this;
419    }
420
421    /**
422     * Configures this {@code Builder} to order entries by value according to the specified
423     * comparator.
424     *
425     * <p>The sort order is stable, that is, if two entries have values that compare as equivalent,
426     * the entry that was inserted first will be first in the built map's iteration order.
427     *
428     * @throws IllegalStateException if this method was already called
429     * @since 19.0
430     */
431    @CanIgnoreReturnValue
432    @Override
433    public Builder<K, V> orderEntriesByValue(Comparator<? super V> valueComparator) {
434      super.orderEntriesByValue(valueComparator);
435      return this;
436    }
437
438    @Override
439    @CanIgnoreReturnValue
440    Builder<K, V> combine(ImmutableMap.Builder<K, V> builder) {
441      super.combine(builder);
442      return this;
443    }
444
445    /**
446     * Returns a newly-created immutable bimap. The iteration order of the returned bimap is the
447     * order in which entries were inserted into the builder, unless {@link #orderEntriesByValue}
448     * was called, in which case entries are sorted by value.
449     *
450     * <p>Prefer the equivalent method {@link #buildOrThrow()} to make it explicit that the method
451     * will throw an exception if there are duplicate keys or values. The {@code build()} method
452     * will soon be deprecated.
453     *
454     * @throws IllegalArgumentException if duplicate keys or values were added
455     */
456    @Override
457    public ImmutableBiMap<K, V> build() {
458      return buildOrThrow();
459    }
460
461    /**
462     * Returns a newly-created immutable bimap, or throws an exception if any key or value was added
463     * more than once. The iteration order of the returned bimap is the order in which entries were
464     * inserted into the builder, unless {@link #orderEntriesByValue} was called, in which case
465     * entries are sorted by value.
466     *
467     * @throws IllegalArgumentException if duplicate keys or values were added
468     * @since 31.0
469     */
470    @Override
471    public ImmutableBiMap<K, V> buildOrThrow() {
472      if (size == 0) {
473        return of();
474      }
475      if (valueComparator != null) {
476        if (entriesUsed) {
477          alternatingKeysAndValues = Arrays.copyOf(alternatingKeysAndValues, 2 * size);
478        }
479        sortEntries(alternatingKeysAndValues, size, valueComparator);
480      }
481      entriesUsed = true;
482      return new RegularImmutableBiMap<K, V>(alternatingKeysAndValues, size);
483    }
484
485    /**
486     * Throws {@link UnsupportedOperationException}. This method is inherited from {@link
487     * ImmutableMap.Builder}, but it does not make sense for bimaps.
488     *
489     * @throws UnsupportedOperationException always
490     * @deprecated This method does not make sense for bimaps and should not be called.
491     * @since 31.1
492     */
493    @DoNotCall
494    @Deprecated
495    @Override
496    public ImmutableBiMap<K, V> buildKeepingLast() {
497      throw new UnsupportedOperationException("Not supported for bimaps");
498    }
499  }
500
501  /**
502   * Returns an immutable bimap containing the same entries as {@code map}. If {@code map} somehow
503   * contains entries with duplicate keys (for example, if it is a {@code SortedMap} whose
504   * comparator is not <i>consistent with equals</i>), the results of this method are undefined.
505   *
506   * <p>The returned {@code BiMap} iterates over entries in the same order as the {@code entrySet}
507   * of the original map.
508   *
509   * <p>Despite the method name, this method attempts to avoid actually copying the data when it is
510   * safe to do so. The exact circumstances under which a copy will or will not be performed are
511   * undocumented and subject to change.
512   *
513   * @throws IllegalArgumentException if two keys have the same value or two values have the same
514   *     key
515   * @throws NullPointerException if any key or value in {@code map} is null
516   */
517  public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
518    if (map instanceof ImmutableBiMap) {
519      @SuppressWarnings("unchecked") // safe since map is not writable
520      ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
521      // TODO(lowasser): if we need to make a copy of a BiMap because the
522      // forward map is a view, don't make a copy of the non-view delegate map
523      if (!bimap.isPartialView()) {
524        return bimap;
525      }
526    }
527    return copyOf(map.entrySet());
528  }
529
530  /**
531   * Returns an immutable bimap containing the given entries. The returned bimap iterates over
532   * entries in the same order as the original iterable.
533   *
534   * @throws IllegalArgumentException if two keys have the same value or two values have the same
535   *     key
536   * @throws NullPointerException if any key, value, or entry is null
537   * @since 19.0
538   */
539  public static <K, V> ImmutableBiMap<K, V> copyOf(
540      Iterable<? extends Entry<? extends K, ? extends V>> entries) {
541    int estimatedSize =
542        (entries instanceof Collection)
543            ? ((Collection<?>) entries).size()
544            : ImmutableCollection.Builder.DEFAULT_INITIAL_CAPACITY;
545    return new Builder<K, V>(estimatedSize).putAll(entries).build();
546  }
547
548  ImmutableBiMap() {}
549
550  /**
551   * {@inheritDoc}
552   *
553   * <p>The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}.
554   */
555  @Override
556  public abstract ImmutableBiMap<V, K> inverse();
557
558  /**
559   * Returns an immutable set of the values in this map, in the same order they appear in {@link
560   * #entrySet}.
561   */
562  @Override
563  public ImmutableSet<V> values() {
564    return inverse().keySet();
565  }
566
567  @Override
568  final ImmutableSet<V> createValues() {
569    throw new AssertionError("should never be called");
570  }
571
572  /**
573   * Guaranteed to throw an exception and leave the bimap unmodified.
574   *
575   * @throws UnsupportedOperationException always
576   * @deprecated Unsupported operation.
577   */
578  @CanIgnoreReturnValue
579  @Deprecated
580  @Override
581  @DoNotCall("Always throws UnsupportedOperationException")
582  @CheckForNull
583  public final V forcePut(K key, V value) {
584    throw new UnsupportedOperationException();
585  }
586
587  /**
588   * Serialized type for all ImmutableBiMap instances. It captures the logical contents and they are
589   * reconstructed using public factory methods. This ensures that the implementation types remain
590   * as implementation details.
591   *
592   * <p>Since the bimap is immutable, ImmutableBiMap doesn't require special logic for keeping the
593   * bimap and its inverse in sync during serialization, the way AbstractBiMap does.
594   */
595  @J2ktIncompatible // serialization
596  private static class SerializedForm<K, V> extends ImmutableMap.SerializedForm<K, V> {
597    SerializedForm(ImmutableBiMap<K, V> bimap) {
598      super(bimap);
599    }
600
601    @Override
602    Builder<K, V> makeBuilder(int size) {
603      return new Builder<>(size);
604    }
605
606    private static final long serialVersionUID = 0;
607  }
608
609  @Override
610  @J2ktIncompatible // serialization
611  Object writeReplace() {
612    return new SerializedForm<>(this);
613  }
614
615  @J2ktIncompatible // serialization
616  private void readObject(ObjectInputStream stream) throws InvalidObjectException {
617    throw new InvalidObjectException("Use SerializedForm");
618  }
619
620  /**
621   * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link
622   * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}.
623   *
624   * @throws UnsupportedOperationException always
625   * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap}.
626   * @since 33.2.0 (available since 21.0 in guava-jre)
627   */
628  @Deprecated
629  @DoNotCall("Use toImmutableBiMap")
630  @SuppressWarnings("Java7ApiChecker")
631  @IgnoreJRERequirement // Users will use this only if they're already using streams.
632  public static <T extends @Nullable Object, K, V>
633      Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
634          Function<? super T, ? extends K> keyFunction,
635          Function<? super T, ? extends V> valueFunction) {
636    throw new UnsupportedOperationException();
637  }
638
639  /**
640   * Not supported. This method does not make sense for {@code BiMap}. This method exists only to
641   * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of
642   * {@code ImmutableBiMap}.
643   *
644   * @throws UnsupportedOperationException always
645   * @deprecated
646   * @since 33.2.0 (available since 21.0 in guava-jre)
647   */
648  @Deprecated
649  @DoNotCall("Use toImmutableBiMap")
650  @SuppressWarnings("Java7ApiChecker")
651  @IgnoreJRERequirement // Users will use this only if they're already using streams.
652  public static <T extends @Nullable Object, K, V>
653      Collector<T, ?, ImmutableMap<K, V>> toImmutableMap(
654          Function<? super T, ? extends K> keyFunction,
655          Function<? super T, ? extends V> valueFunction,
656          BinaryOperator<V> mergeFunction) {
657    throw new UnsupportedOperationException();
658  }
659
660  private static final long serialVersionUID = 0xdecaf;
661}