All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.collect.super.com.google.common.collect.ImmutableSortedMap Maven / Gradle / Ivy

Go to download

Guava is a suite of core and expanded libraries that include utility classes, Google's collections, I/O classes, and much more. This project includes GWT-friendly sources.

There is a newer version: 33.1.0-jre
Show newest version
/*
 * Copyright (C) 2009 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.newTreeMap;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableSortedMap;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * GWT emulated version of {@link com.google.common.collect.ImmutableSortedMap}. It's a thin wrapper
 * around a {@link java.util.TreeMap}.
 *
 * @author Hayward Chan
 */
public final class ImmutableSortedMap extends ForwardingImmutableMap
    implements SortedMap {

  @SuppressWarnings("unchecked")
  static final Comparator NATURAL_ORDER = Ordering.natural();

  // This reference is only used by GWT compiler to infer the keys and values
  // of the map that needs to be serialized.
  private Comparator unusedComparatorForSerialization;
  private K unusedKeyForSerialization;
  private V unusedValueForSerialization;

  private final transient SortedMap sortedDelegate;

  // The comparator used by this map.  It's the same as that of sortedDelegate,
  // except that when sortedDelegate's comparator is null, it points to a
  // non-null instance of Ordering.natural().
  // (cpovirk: Is sortedDelegate's comparator really ever null?)
  // The comparator will likely also differ because of our nullAccepting hack.
  // See the bottom of the file for more information about it.
  private final transient Comparator comparator;

  ImmutableSortedMap(SortedMap delegate, Comparator comparator) {
    super(delegate);
    this.comparator = comparator;
    this.sortedDelegate = delegate;
  }

  public static  Collector> toImmutableSortedMap(
      Comparator comparator,
      Function keyFunction,
      Function valueFunction) {
    return CollectCollectors.toImmutableSortedMap(comparator, keyFunction, valueFunction);
  }

  public static  Collector> toImmutableSortedMap(
      Comparator comparator,
      Function keyFunction,
      Function valueFunction,
      BinaryOperator mergeFunction) {
    checkNotNull(comparator);
    checkNotNull(keyFunction);
    checkNotNull(valueFunction);
    checkNotNull(mergeFunction);
    return Collectors.collectingAndThen(
        Collectors.toMap(
            keyFunction, valueFunction, mergeFunction, () -> new TreeMap(comparator)),
        ImmutableSortedMap::copyOfSorted);
  }

  // Casting to any type is safe because the set will never hold any elements.
  @SuppressWarnings("unchecked")
  public static  ImmutableSortedMap of() {
    return new Builder(NATURAL_ORDER).build();
  }

  public static , V> ImmutableSortedMap of(K k1, V v1) {
    return copyOf(singletonMap(k1, v1));
  }

  public static , V> ImmutableSortedMap of(
      K k1, V v1, K k2, V v2) {
    return new Builder(Ordering.natural()).put(k1, v1).put(k2, v2).build();
  }

  public static , V> ImmutableSortedMap of(
      K k1, V v1, K k2, V v2, K k3, V v3) {
    return new Builder(Ordering.natural()).put(k1, v1).put(k2, v2).put(k3, v3).build();
  }

  public static , V> ImmutableSortedMap of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .put(k6, v6)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      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) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .put(k6, v6)
        .put(k7, v7)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      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,
      K k8,
      V v8) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .put(k6, v6)
        .put(k7, v7)
        .put(k8, v8)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      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,
      K k8,
      V v8,
      K k9,
      V v9) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .put(k6, v6)
        .put(k7, v7)
        .put(k8, v8)
        .put(k9, v9)
        .build();
  }

  public static , V> ImmutableSortedMap of(
      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,
      K k8,
      V v8,
      K k9,
      V v9,
      K k10,
      V v10) {
    return new Builder(Ordering.natural())
        .put(k1, v1)
        .put(k2, v2)
        .put(k3, v3)
        .put(k4, v4)
        .put(k5, v5)
        .put(k6, v6)
        .put(k7, v7)
        .put(k8, v8)
        .put(k9, v9)
        .put(k10, v10)
        .build();
  }

  public static  ImmutableSortedMap copyOf(Map map) {
    return copyOfInternal((Map) map, (Ordering) Ordering.natural());
  }

  public static  ImmutableSortedMap copyOf(
      Map map, Comparator comparator) {
    return copyOfInternal(map, checkNotNull(comparator));
  }

  public static  ImmutableSortedMap copyOf(
      Iterable> entries) {
    return new Builder(NATURAL_ORDER).putAll(entries).build();
  }

  public static  ImmutableSortedMap copyOf(
      Iterable> entries,
      Comparator comparator) {
    return new Builder(comparator).putAll(entries).build();
  }

  public static  ImmutableSortedMap copyOfSorted(SortedMap map) {
    // If map has a null comparator, the keys should have a natural ordering,
    // even though K doesn't explicitly implement Comparable.
    @SuppressWarnings("unchecked")
    Comparator comparator =
        (map.comparator() == null) ? NATURAL_ORDER : map.comparator();
    return copyOfInternal(map, comparator);
  }

  private static  ImmutableSortedMap copyOfInternal(
      Map map, Comparator comparator) {

    if (map instanceof ImmutableSortedMap) {
      // TODO: Prove that this cast is safe, even though
      // Collections.unmodifiableSortedMap requires the same key type.
      @SuppressWarnings("unchecked")
      ImmutableSortedMap kvMap = (ImmutableSortedMap) map;
      Comparator comparator2 = kvMap.comparator();
      boolean sameComparator =
          (comparator2 == null) ? comparator == NATURAL_ORDER : comparator.equals(comparator2);
      if (sameComparator) {
        return kvMap;
      }
    }

    SortedMap delegate = newModifiableDelegate(comparator);
    for (Entry entry : map.entrySet()) {
      putEntryWithChecks(delegate, entry);
    }
    return newView(unmodifiableSortedMap(delegate), comparator);
  }

  private static  void putEntryWithChecks(
      SortedMap map, Entry entry) {
    K key = checkNotNull(entry.getKey());
    V value = checkNotNull(entry.getValue());
    if (map.containsKey(key)) {
      // When a collision happens, the colliding entry is the first entry
      // of the tail map.
      Entry previousEntry = map.tailMap(key).entrySet().iterator().next();
      throw new IllegalArgumentException(
          "Duplicate keys in mappings "
              + previousEntry.getKey()
              + "="
              + previousEntry.getValue()
              + " and "
              + key
              + "="
              + value);
    }
    map.put(key, value);
  }

  public static , V> Builder naturalOrder() {
    return new Builder(Ordering.natural());
  }

  public static  Builder orderedBy(Comparator comparator) {
    return new Builder(comparator);
  }

  public static , V> Builder reverseOrder() {
    return new Builder(Ordering.natural().reverse());
  }

  public static final class Builder extends ImmutableMap.Builder {
    private final Comparator comparator;

    public Builder(Comparator comparator) {
      this.comparator = checkNotNull(comparator);
    }

    @Override
    public Builder put(K key, V value) {
      entries.add(entryOf(key, value));
      return this;
    }

    @Override
    public Builder put(Entry entry) {
      super.put(entry);
      return this;
    }

    @Override
    public Builder putAll(Map map) {
      return putAll(map.entrySet());
    }

    @Override
    public Builder putAll(Iterable> entries) {
      for (Entry entry : entries) {
        put(entry);
      }
      return this;
    }

    Builder combine(Builder other) {
      super.combine(other);
      return this;
    }

    @Override
    public Builder orderEntriesByValue(Comparator valueComparator) {
      throw new UnsupportedOperationException("Not available on ImmutableSortedMap.Builder");
    }

    @Override
    public ImmutableSortedMap build() {
      return buildOrThrow();
    }

    @Override
    public ImmutableSortedMap buildOrThrow() {
      SortedMap delegate = newModifiableDelegate(comparator);
      for (Entry entry : entries) {
        putEntryWithChecks(delegate, entry);
      }
      return newView(unmodifiableSortedMap(delegate), comparator);
    }
  }

  private transient ImmutableSortedSet keySet;

  @Override
  public ImmutableSortedSet keySet() {
    ImmutableSortedSet ks = keySet;
    return (ks == null) ? (keySet = createKeySet()) : ks;
  }

  @Override
  ImmutableSortedSet createKeySet() {
    // the keySet() of the delegate is only a Set and TreeMap.navigatableKeySet
    // is not available in GWT yet.  To keep the code simple and code size more,
    // we make a copy here, instead of creating a view of it.
    //
    // TODO: revisit if it's unbearably slow or when GWT supports
    // TreeMap.navigatbleKeySet().
    return ImmutableSortedSet.copyOf(comparator, sortedDelegate.keySet());
  }

  public Comparator comparator() {
    return comparator;
  }

  public K firstKey() {
    return sortedDelegate.firstKey();
  }

  public K lastKey() {
    return sortedDelegate.lastKey();
  }

  K higher(K k) {
    Iterator iterator = keySet().tailSet(k).iterator();
    while (iterator.hasNext()) {
      K tmp = iterator.next();
      if (comparator().compare(k, tmp) < 0) {
        return tmp;
      }
    }
    return null;
  }

  public ImmutableSortedMap headMap(K toKey) {
    checkNotNull(toKey);
    return newView(sortedDelegate.headMap(toKey));
  }

  ImmutableSortedMap headMap(K toKey, boolean inclusive) {
    checkNotNull(toKey);
    if (inclusive) {
      K tmp = higher(toKey);
      if (tmp == null) {
        return this;
      }
      toKey = tmp;
    }
    return headMap(toKey);
  }

  public ImmutableSortedMap subMap(K fromKey, K toKey) {
    checkNotNull(fromKey);
    checkNotNull(toKey);
    checkArgument(comparator.compare(fromKey, toKey) <= 0);
    return newView(sortedDelegate.subMap(fromKey, toKey));
  }

  ImmutableSortedMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
    checkNotNull(fromKey);
    checkNotNull(toKey);
    checkArgument(comparator.compare(fromKey, toKey) <= 0);
    return tailMap(fromKey, fromInclusive).headMap(toKey, toInclusive);
  }

  public ImmutableSortedMap tailMap(K fromKey) {
    checkNotNull(fromKey);
    return newView(sortedDelegate.tailMap(fromKey));
  }

  public ImmutableSortedMap tailMap(K fromKey, boolean inclusive) {
    checkNotNull(fromKey);
    if (!inclusive) {
      fromKey = higher(fromKey);
      if (fromKey == null) {
        return new Builder(this.comparator).build();
      }
    }
    return tailMap(fromKey);
  }

  private ImmutableSortedMap newView(SortedMap delegate) {
    return newView(delegate, comparator);
  }

  private static  ImmutableSortedMap newView(
      SortedMap delegate, Comparator comparator) {
    return new ImmutableSortedMap(delegate, comparator);
  }

  /*
   * We don't permit nulls, but we wrap every comparator with nullsFirst().
   * Why? We want for queries like containsKey(null) to return false, but the
   * GWT SortedMap implementation that we delegate to throws
   * NullPointerException if the comparator does. Since our construction
   * methods ensure that null is never present in the map, it's OK for the
   * comparator to look for it wherever it wants.
   *
   * Note that we do NOT touch the comparator returned by comparator(), which
   * should be identical to the one the user passed in. We touch only the
   * "secret" comparator used by the delegate implementation.
   */

  private static  SortedMap newModifiableDelegate(Comparator comparator) {
    return newTreeMap(nullAccepting(comparator));
  }

  private static  Comparator nullAccepting(Comparator comparator) {
    return Ordering.from(comparator).nullsFirst();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy