alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MapsTest.java)

This example Java source code file (MapsTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

double, gwtincompatible, illegalargumentexception, integer, length_function, map, mapdifference, navigablemap, number, object, override, reflection, sortedmap, string, threading, threads, unsupportedoperationexception, util

The MapsTest.java Java example source code

/*
 * Copyright (C) 2007 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.collect.Maps.transformEntries;
import static com.google.common.collect.Maps.transformValues;
import static com.google.common.collect.Maps.unmodifiableNavigableMap;
import static com.google.common.collect.testing.Helpers.mapEntry;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Converter;
import com.google.common.base.Equivalence;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Maps.EntryTransformer;
import com.google.common.collect.Maps.ValueDifferenceImpl;
import com.google.common.collect.SetsTest.Derived;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.SerializableTester;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Unit test for {@code Maps}.
 *
 * @author Kevin Bourrillion
 * @author Mike Bostock
 * @author Jared Levy
 */
@GwtCompatible(emulated = true)
public class MapsTest extends TestCase {

  private static final Comparator<Integer> SOME_COMPARATOR =
      Collections.reverseOrder();

  public void testHashMap() {
    HashMap<Integer, Integer> map = Maps.newHashMap();
    assertEquals(Collections.emptyMap(), map);
  }

  public void testHashMapWithInitialMap() {
    Map<String, Integer> original = new TreeMap();
    original.put("a", 1);
    original.put("b", 2);
    original.put("c", 3);
    HashMap<String, Integer> map = Maps.newHashMap(original);
    assertEquals(original, map);
  }

  public void testHashMapGeneralizesTypes() {
    Map<String, Integer> original = new TreeMap();
    original.put("a", 1);
    original.put("b", 2);
    original.put("c", 3);
    HashMap<Object, Object> map =
        Maps.newHashMap((Map<? extends Object, ? extends Object>) original);
    assertEquals(original, map);
  }

  public void testCapacityForNegativeSizeFails() {
    try {
      Maps.capacity(-1);
      fail("Negative expected size must result in IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  /**
   * Tests that nHMWES makes hash maps large enough that adding the expected
   * number of elements won't cause a rehash.
   *
   * As of jdk7u40, HashMap has an empty-map optimization.  The argument to
   * new HashMap(int) is noted, but the initial table is a zero-length array.
   *
   * This test may fail miserably on non-OpenJDK environments...
   */
  @GwtIncompatible // reflection
  @AndroidIncompatible // relies on assumptions about OpenJDK
  public void testNewHashMapWithExpectedSize_wontGrow() throws Exception {
    // before jdk7u40: creates one-bucket table
    // after  jdk7u40: creates empty table
    assertTrue(bucketsOf(Maps.newHashMapWithExpectedSize(0)) <= 1);

    for (int size = 1; size < 200; size++) {
      assertWontGrow(size,
          Maps.newHashMapWithExpectedSize(size),
          Maps.newHashMapWithExpectedSize(size));
    }
  }

  /**
   * Same test as above but for newLinkedHashMapWithExpectedSize
   */
  @GwtIncompatible // reflection
  @AndroidIncompatible // relies on assumptions about OpenJDK
  public void testNewLinkedHashMapWithExpectedSize_wontGrow() throws Exception {
    assertTrue(bucketsOf(Maps.newLinkedHashMapWithExpectedSize(0)) <= 1);

    for (int size = 1; size < 200; size++) {
      assertWontGrow(size,
          Maps.newLinkedHashMapWithExpectedSize(size),
          Maps.newLinkedHashMapWithExpectedSize(size));
    }
  }

  @GwtIncompatible // reflection
  private static void assertWontGrow(
      int size, HashMap<Object, Object> map1, HashMap map2) throws Exception {
    // Only start measuring table size after the first element inserted, to
    // deal with empty-map optimization.
    map1.put(0, null);

    int initialBuckets = bucketsOf(map1);

    for (int i = 1; i < size; i++) {
      map1.put(i, null);
    }
    assertThat(bucketsOf(map1))
        .named("table size after adding " + size + " elements")
        .isEqualTo(initialBuckets);

    /*
     * Something slightly different happens when the entries are added all at
     * once; make sure that passes too.
     */
    map2.putAll(map1);
    assertThat(bucketsOf(map1))
        .named("table size after adding " + size + " elements")
        .isEqualTo(initialBuckets);
  }

  @GwtIncompatible // reflection
  private static int bucketsOf(HashMap<?, ?> hashMap) throws Exception {
    Field tableField = HashMap.class.getDeclaredField("table");
    tableField.setAccessible(true);
    Object[] table = (Object[]) tableField.get(hashMap);
    // In JDK8, table is set lazily, so it may be null.
    return table == null ? 0 : table.length;
  }

  public void testCapacityForLargeSizes() {
    int[] largeExpectedSizes = new int[] {
      Integer.MAX_VALUE / 2 - 1,
      Integer.MAX_VALUE / 2,
      Integer.MAX_VALUE / 2 + 1,
      Integer.MAX_VALUE - 1,
      Integer.MAX_VALUE};
    for (int expectedSize : largeExpectedSizes) {
      int capacity = Maps.capacity(expectedSize);
      assertTrue(
          "capacity (" + capacity + ") must be >= expectedSize (" + expectedSize + ")",
          capacity >= expectedSize);
    }
  }

  public void testLinkedHashMap() {
    LinkedHashMap<Integer, Integer> map = Maps.newLinkedHashMap();
    assertEquals(Collections.emptyMap(), map);
  }

  @SuppressWarnings("serial")
  public void testLinkedHashMapWithInitialMap() {
    Map<String, String> map = new LinkedHashMap() {{
      put("Hello", "World");
      put("first", "second");
      put("polygene", "lubricants");
      put("alpha", "betical");
    }};

    LinkedHashMap<String, String> copy = Maps.newLinkedHashMap(map);

    Iterator<Entry iter = copy.entrySet().iterator();
    assertTrue(iter.hasNext());
    Entry<String, String> entry = iter.next();
    assertEquals("Hello", entry.getKey());
    assertEquals("World", entry.getValue());
    assertTrue(iter.hasNext());

    entry = iter.next();
    assertEquals("first", entry.getKey());
    assertEquals("second", entry.getValue());
    assertTrue(iter.hasNext());

    entry = iter.next();
    assertEquals("polygene", entry.getKey());
    assertEquals("lubricants", entry.getValue());
    assertTrue(iter.hasNext());

    entry = iter.next();
    assertEquals("alpha", entry.getKey());
    assertEquals("betical", entry.getValue());
    assertFalse(iter.hasNext());
  }

  public void testLinkedHashMapGeneralizesTypes() {
    Map<String, Integer> original = new LinkedHashMap();
    original.put("a", 1);
    original.put("b", 2);
    original.put("c", 3);
    HashMap<Object, Object> map
        = Maps.<Object, Object>newLinkedHashMap(original);
    assertEquals(original, map);
  }

  public void testIdentityHashMap() {
    IdentityHashMap<Integer, Integer> map = Maps.newIdentityHashMap();
    assertEquals(Collections.emptyMap(), map);
  }

  public void testConcurrentMap() {
    ConcurrentMap<Integer, Integer> map = Maps.newConcurrentMap();
    assertEquals(Collections.emptyMap(), map);
  }

  public void testTreeMap() {
    TreeMap<Integer, Integer> map = Maps.newTreeMap();
    assertEquals(Collections.emptyMap(), map);
    assertNull(map.comparator());
  }

  public void testTreeMapDerived() {
    TreeMap<Derived, Integer> map = Maps.newTreeMap();
    assertEquals(Collections.emptyMap(), map);
    map.put(new Derived("foo"), 1);
    map.put(new Derived("bar"), 2);
    assertThat(map.keySet()).containsExactly(
        new Derived("bar"), new Derived("foo")).inOrder();
    assertThat(map.values()).containsExactly(2, 1).inOrder();
    assertNull(map.comparator());
  }

  public void testTreeMapNonGeneric() {
    TreeMap<LegacyComparable, Integer> map = Maps.newTreeMap();
    assertEquals(Collections.emptyMap(), map);
    map.put(new LegacyComparable("foo"), 1);
    map.put(new LegacyComparable("bar"), 2);
    assertThat(map.keySet()).containsExactly(
        new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder();
    assertThat(map.values()).containsExactly(2, 1).inOrder();
    assertNull(map.comparator());
  }

  public void testTreeMapWithComparator() {
    TreeMap<Integer, Integer> map = Maps.newTreeMap(SOME_COMPARATOR);
    assertEquals(Collections.emptyMap(), map);
    assertSame(SOME_COMPARATOR, map.comparator());
  }

  public void testTreeMapWithInitialMap() {
    SortedMap<Integer, Integer> map = Maps.newTreeMap();
    map.put(5, 10);
    map.put(3, 20);
    map.put(1, 30);
    TreeMap<Integer, Integer> copy = Maps.newTreeMap(map);
    assertEquals(copy, map);
    assertSame(copy.comparator(), map.comparator());
  }

  public enum SomeEnum { SOME_INSTANCE }

  public void testEnumMap() {
    EnumMap<SomeEnum, Integer> map = Maps.newEnumMap(SomeEnum.class);
    assertEquals(Collections.emptyMap(), map);
    map.put(SomeEnum.SOME_INSTANCE, 0);
    assertEquals(Collections.singletonMap(SomeEnum.SOME_INSTANCE, 0), map);
  }

  public void testEnumMapNullClass() {
    try {
      Maps.<SomeEnum, Long>newEnumMap((Class) null);
      fail("no exception thrown");
    } catch (NullPointerException expected) {
    }
  }

  public void testEnumMapWithInitialEnumMap() {
    EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class);
    original.put(SomeEnum.SOME_INSTANCE, 0);
    EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
    assertEquals(original, copy);
  }

  public void testEnumMapWithInitialEmptyEnumMap() {
    EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class);
    EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
    assertEquals(original, copy);
    assertNotSame(original, copy);
  }

  public void testEnumMapWithInitialMap() {
    HashMap<SomeEnum, Integer> original = Maps.newHashMap();
    original.put(SomeEnum.SOME_INSTANCE, 0);
    EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original);
    assertEquals(original, copy);
  }

  public void testEnumMapWithInitialEmptyMap() {
    Map<SomeEnum, Integer> original = Maps.newHashMap();
    try {
      Maps.newEnumMap(original);
      fail("Empty map must result in an IllegalArgumentException");
    } catch (IllegalArgumentException expected) {}
  }

  public void testToStringImplWithNullKeys() throws Exception {
    Map<String, String> hashmap = Maps.newHashMap();
    hashmap.put("foo", "bar");
    hashmap.put(null, "baz");

    assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap));
  }

  public void testToStringImplWithNullValues() throws Exception {
    Map<String, String> hashmap = Maps.newHashMap();
    hashmap.put("foo", "bar");
    hashmap.put("baz", null);

    assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap));
  }

  @GwtIncompatible // NullPointerTester
  public void testNullPointerExceptions() {
    new NullPointerTester().testAllPublicStaticMethods(Maps.class);
  }

  private static final Map<Integer, Integer> EMPTY
      = Collections.emptyMap();
  private static final Map<Integer, Integer> SINGLETON
      = Collections.singletonMap(1, 2);

  public void testMapDifferenceEmptyEmpty() {
    MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, EMPTY);
    assertTrue(diff.areEqual());
    assertEquals(EMPTY, diff.entriesOnlyOnLeft());
    assertEquals(EMPTY, diff.entriesOnlyOnRight());
    assertEquals(EMPTY, diff.entriesInCommon());
    assertEquals(EMPTY, diff.entriesDiffering());
    assertEquals("equal", diff.toString());
  }

  public void testMapDifferenceEmptySingleton() {
    MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, SINGLETON);
    assertFalse(diff.areEqual());
    assertEquals(EMPTY, diff.entriesOnlyOnLeft());
    assertEquals(SINGLETON, diff.entriesOnlyOnRight());
    assertEquals(EMPTY, diff.entriesInCommon());
    assertEquals(EMPTY, diff.entriesDiffering());
    assertEquals("not equal: only on right={1=2}", diff.toString());
  }

  public void testMapDifferenceSingletonEmpty() {
    MapDifference<Integer, Integer> diff = Maps.difference(SINGLETON, EMPTY);
    assertFalse(diff.areEqual());
    assertEquals(SINGLETON, diff.entriesOnlyOnLeft());
    assertEquals(EMPTY, diff.entriesOnlyOnRight());
    assertEquals(EMPTY, diff.entriesInCommon());
    assertEquals(EMPTY, diff.entriesDiffering());
    assertEquals("not equal: only on left={1=2}", diff.toString());
  }

  public void testMapDifferenceTypical() {
    Map<Integer, String> left = ImmutableMap.of(
        1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
    Map<Integer, String> right = ImmutableMap.of(
        1, "a", 3, "f", 5, "g", 6, "z");

    MapDifference<Integer, String> diff1 = Maps.difference(left, right);
    assertFalse(diff1.areEqual());
    assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft());
    assertEquals(ImmutableMap.of(6, "z"), diff1.entriesOnlyOnRight());
    assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon());
    assertEquals(ImmutableMap.of(3,
        ValueDifferenceImpl.create("c", "f"), 5,
        ValueDifferenceImpl.create("e", "g")),
        diff1.entriesDiffering());
    assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=z}: "
        + "value differences={3=(c, f), 5=(e, g)}", diff1.toString());

    MapDifference<Integer, String> diff2 = Maps.difference(right, left);
    assertFalse(diff2.areEqual());
    assertEquals(ImmutableMap.of(6, "z"), diff2.entriesOnlyOnLeft());
    assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight());
    assertEquals(ImmutableMap.of(1, "a"), diff2.entriesInCommon());
    assertEquals(ImmutableMap.of(3,
        ValueDifferenceImpl.create("f", "c"), 5,
        ValueDifferenceImpl.create("g", "e")),
        diff2.entriesDiffering());
    assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: "
        + "value differences={3=(f, c), 5=(g, e)}", diff2.toString());
  }

  public void testMapDifferenceEquals() {
    Map<Integer, String> left = ImmutableMap.of(
        1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
    Map<Integer, String> right = ImmutableMap.of(
        1, "a", 3, "f", 5, "g", 6, "z");
    Map<Integer, String> right2 = ImmutableMap.of(
        1, "a", 3, "h", 5, "g", 6, "z");
    MapDifference<Integer, String> original = Maps.difference(left, right);
    MapDifference<Integer, String> same = Maps.difference(left, right);
    MapDifference<Integer, String> reverse = Maps.difference(right, left);
    MapDifference<Integer, String> diff2 = Maps.difference(left, right2);

    new EqualsTester()
        .addEqualityGroup(original, same)
        .addEqualityGroup(reverse)
        .addEqualityGroup(diff2)
        .testEquals();
  }

  public void testMapDifferencePredicateTypical() {
    Map<Integer, String> left = ImmutableMap.of(
        1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
    Map<Integer, String> right = ImmutableMap.of(
        1, "A", 3, "F", 5, "G", 6, "Z");

    // TODO(kevinb): replace with Ascii.caseInsensitiveEquivalence() when it
    // exists
    Equivalence<String> caseInsensitiveEquivalence = Equivalence.equals().onResultOf(
        new Function<String, String>() {
          @Override public String apply(String input) {
            return input.toLowerCase();
          }
        });

    MapDifference<Integer, String> diff1 = Maps.difference(left, right,
        caseInsensitiveEquivalence);
    assertFalse(diff1.areEqual());
    assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft());
    assertEquals(ImmutableMap.of(6, "Z"), diff1.entriesOnlyOnRight());
    assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon());
    assertEquals(ImmutableMap.of(3,
        ValueDifferenceImpl.create("c", "F"), 5,
        ValueDifferenceImpl.create("e", "G")),
        diff1.entriesDiffering());
    assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=Z}: "
        + "value differences={3=(c, F), 5=(e, G)}", diff1.toString());

    MapDifference<Integer, String> diff2 = Maps.difference(right, left,
        caseInsensitiveEquivalence);
    assertFalse(diff2.areEqual());
    assertEquals(ImmutableMap.of(6, "Z"), diff2.entriesOnlyOnLeft());
    assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight());
    assertEquals(ImmutableMap.of(1, "A"), diff2.entriesInCommon());
    assertEquals(ImmutableMap.of(3,
        ValueDifferenceImpl.create("F", "c"), 5,
        ValueDifferenceImpl.create("G", "e")),
        diff2.entriesDiffering());
    assertEquals("not equal: only on left={6=Z}: only on right={2=b, 4=d}: "
        + "value differences={3=(F, c), 5=(G, e)}", diff2.toString());
  }

  private static final SortedMap<Integer, Integer> SORTED_EMPTY = Maps.newTreeMap();
  private static final SortedMap<Integer, Integer> SORTED_SINGLETON =
      ImmutableSortedMap.of(1, 2);

  public void testMapDifferenceOfSortedMapIsSorted() {
    Map<Integer, Integer> map = SORTED_SINGLETON;
    MapDifference<Integer, Integer> difference = Maps.difference(map, EMPTY);
    assertTrue(difference instanceof SortedMapDifference);
  }

  public void testSortedMapDifferenceEmptyEmpty() {
    SortedMapDifference<Integer, Integer> diff =
        Maps.difference(SORTED_EMPTY, SORTED_EMPTY);
    assertTrue(diff.areEqual());
    assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft());
    assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight());
    assertEquals(SORTED_EMPTY, diff.entriesInCommon());
    assertEquals(SORTED_EMPTY, diff.entriesDiffering());
    assertEquals("equal", diff.toString());
  }

  public void testSortedMapDifferenceEmptySingleton() {
    SortedMapDifference<Integer, Integer> diff =
        Maps.difference(SORTED_EMPTY, SORTED_SINGLETON);
    assertFalse(diff.areEqual());
    assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft());
    assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnRight());
    assertEquals(SORTED_EMPTY, diff.entriesInCommon());
    assertEquals(SORTED_EMPTY, diff.entriesDiffering());
    assertEquals("not equal: only on right={1=2}", diff.toString());
  }

  public void testSortedMapDifferenceSingletonEmpty() {
    SortedMapDifference<Integer, Integer> diff =
        Maps.difference(SORTED_SINGLETON, SORTED_EMPTY);
    assertFalse(diff.areEqual());
    assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnLeft());
    assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight());
    assertEquals(SORTED_EMPTY, diff.entriesInCommon());
    assertEquals(SORTED_EMPTY, diff.entriesDiffering());
    assertEquals("not equal: only on left={1=2}", diff.toString());
  }

  public void testSortedMapDifferenceTypical() {
    SortedMap<Integer, String> left =
        ImmutableSortedMap.<Integer, String>reverseOrder()
        .put(1, "a").put(2, "b").put(3, "c").put(4, "d").put(5, "e")
        .build();

    SortedMap<Integer, String> right =
        ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z");

    SortedMapDifference<Integer, String> diff1 =
        Maps.difference(left, right);
    assertFalse(diff1.areEqual());
    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
        Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder();
    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
        Maps.immutableEntry(6, "z"));
    assertThat(diff1.entriesInCommon().entrySet()).contains(
        Maps.immutableEntry(1, "a"));
    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
        Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")),
        Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder();
    assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: "
        + "value differences={5=(e, g), 3=(c, f)}", diff1.toString());

    SortedMapDifference<Integer, String> diff2 =
        Maps.difference(right, left);
    assertFalse(diff2.areEqual());
    assertThat(diff2.entriesOnlyOnLeft().entrySet()).contains(
        Maps.immutableEntry(6, "z"));
    assertThat(diff2.entriesOnlyOnRight().entrySet()).containsExactly(
        Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
    assertThat(diff1.entriesInCommon().entrySet()).contains(
        Maps.immutableEntry(1, "a"));
    assertEquals(ImmutableMap.of(
            3, ValueDifferenceImpl.create("f", "c"),
            5, ValueDifferenceImpl.create("g", "e")),
        diff2.entriesDiffering());
    assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: "
        + "value differences={3=(f, c), 5=(g, e)}", diff2.toString());
  }

  public void testSortedMapDifferenceImmutable() {
    SortedMap<Integer, String> left = Maps.newTreeMap(
        ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"));
    SortedMap<Integer, String> right =
        Maps.newTreeMap(ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"));

    SortedMapDifference<Integer, String> diff1 =
        Maps.difference(left, right);
    left.put(6, "z");
    assertFalse(diff1.areEqual());
    assertThat(diff1.entriesOnlyOnLeft().entrySet()).containsExactly(
        Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder();
    assertThat(diff1.entriesOnlyOnRight().entrySet()).contains(
        Maps.immutableEntry(6, "z"));
    assertThat(diff1.entriesInCommon().entrySet()).contains(
        Maps.immutableEntry(1, "a"));
    assertThat(diff1.entriesDiffering().entrySet()).containsExactly(
        Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")),
        Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder();
    try {
      diff1.entriesInCommon().put(7, "x");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      diff1.entriesOnlyOnLeft().put(7, "x");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      diff1.entriesOnlyOnRight().put(7, "x");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
  }

  public void testSortedMapDifferenceEquals() {
    SortedMap<Integer, String> left =
        ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e");
    SortedMap<Integer, String> right =
        ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z");
    SortedMap<Integer, String> right2 =
        ImmutableSortedMap.of(1, "a", 3, "h", 5, "g", 6, "z");
    SortedMapDifference<Integer, String> original =
        Maps.difference(left, right);
    SortedMapDifference<Integer, String> same =
        Maps.difference(left, right);
    SortedMapDifference<Integer, String> reverse =
        Maps.difference(right, left);
    SortedMapDifference<Integer, String> diff2 =
        Maps.difference(left, right2);

    new EqualsTester()
        .addEqualityGroup(original, same)
        .addEqualityGroup(reverse)
        .addEqualityGroup(diff2)
        .testEquals();
  }

  private static final Function<String, Integer> LENGTH_FUNCTION =
      new Function<String, Integer>() {
        @Override
        public Integer apply(String input) {
          return input.length();
        }
      };

  public void testAsMap() {
    Set<String> strings = ImmutableSet.of("one", "two", "three");
    Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(5), map.get("three"));
    assertNull(map.get("five"));
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("two", 3),
        mapEntry("three", 5)).inOrder();
  }

  public void testAsMapReadsThrough() {
    Set<String> strings = Sets.newLinkedHashSet();
    Collections.addAll(strings, "one", "two", "three");
    Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertNull(map.get("four"));
    strings.add("four");
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5, "four", 4), map);
    assertEquals(Integer.valueOf(4), map.get("four"));
  }

  public void testAsMapWritesThrough() {
    Set<String> strings = Sets.newLinkedHashSet();
    Collections.addAll(strings, "one", "two", "three");
    Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(3), map.remove("two"));
    assertThat(strings).containsExactly("one", "three").inOrder();
  }

  public void testAsMapEmpty() {
    Set<String> strings = ImmutableSet.of();
    Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertThat(map.entrySet()).isEmpty();
    assertTrue(map.isEmpty());
    assertNull(map.get("five"));
  }

  private static class NonNavigableSortedSet
      extends ForwardingSortedSet<String> {
    private final SortedSet<String> delegate = Sets.newTreeSet();

    @Override
    protected SortedSet<String> delegate() {
      return delegate;
    }
  }

  public void testAsMapSorted() {
    SortedSet<String> strings = new NonNavigableSortedSet();
    Collections.addAll(strings, "one", "two", "three");
    SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(5), map.get("three"));
    assertNull(map.get("five"));
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();
    assertThat(map.tailMap("onea").entrySet()).containsExactly(
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();
    assertThat(map.subMap("one", "two").entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("three", 5)).inOrder();
  }

  public void testAsMapSortedReadsThrough() {
    SortedSet<String> strings = new NonNavigableSortedSet();
    Collections.addAll(strings, "one", "two", "three");
    SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertNull(map.comparator());
    assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map);
    assertNull(map.get("four"));
    strings.add("four");
    assertEquals(
        ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4),
        map);
    assertEquals(Integer.valueOf(4), map.get("four"));
    SortedMap<String, Integer> headMap = map.headMap("two");
    assertEquals(
        ImmutableSortedMap.of("four", 4, "one", 3, "three", 5),
        headMap);
    strings.add("five");
    strings.remove("one");
    assertEquals(
        ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
        headMap);
    assertThat(map.entrySet()).containsExactly(
        mapEntry("five", 4),
        mapEntry("four", 4),
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();
  }

  public void testAsMapSortedWritesThrough() {
    SortedSet<String> strings = new NonNavigableSortedSet();
    Collections.addAll(strings, "one", "two", "three");
    SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(3), map.remove("two"));
    assertThat(strings).containsExactly("one", "three").inOrder();
  }

  public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() {
    SortedMap<String, Integer> map = Maps.asMap(
        new NonNavigableSortedSet(), LENGTH_FUNCTION);
    try {
      map.subMap("a", "z").keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.tailMap("a").keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.headMap("r").keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.headMap("r").tailMap("m").keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
  }

  public void testAsMapSortedEmpty() {
    SortedSet<String> strings = new NonNavigableSortedSet();
    SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertThat(map.entrySet()).isEmpty();
    assertTrue(map.isEmpty());
    assertNull(map.get("five"));
  }

  @GwtIncompatible // NavigableMap
  public void testAsMapNavigable() {
    NavigableSet<String> strings =
        Sets.newTreeSet(asList("one", "two", "three"));
    NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(5), map.get("three"));
    assertNull(map.get("five"));
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();
    assertThat(map.tailMap("onea").entrySet()).containsExactly(
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();
    assertThat(map.subMap("one", "two").entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("three", 5)).inOrder();

    assertEquals(ImmutableSortedMap.of("two", 3, "three", 5),
        map.tailMap("three", true));
    assertEquals(ImmutableSortedMap.of("one", 3, "three", 5),
        map.headMap("two", false));
    assertEquals(ImmutableSortedMap.of("three", 5),
        map.subMap("one", false, "tr", true));

    assertEquals("three", map.higherKey("one"));
    assertEquals("three", map.higherKey("r"));
    assertEquals("three", map.ceilingKey("r"));
    assertEquals("one", map.ceilingKey("one"));
    assertEquals(mapEntry("three", 5), map.higherEntry("one"));
    assertEquals(mapEntry("one", 3), map.ceilingEntry("one"));
    assertEquals("one", map.lowerKey("three"));
    assertEquals("one", map.lowerKey("r"));
    assertEquals("one", map.floorKey("r"));
    assertEquals("three", map.floorKey("three"));

    assertThat(map.descendingMap().entrySet()).containsExactly(
        mapEntry("two", 3),
        mapEntry("three", 5),
        mapEntry("one", 3)).inOrder();
    assertEquals(map.headMap("three", true),
        map.descendingMap().tailMap("three", true));
    assertThat(map.tailMap("three", false).entrySet()).contains(
        mapEntry("two", 3));
    assertNull(map.tailMap("three", true).lowerEntry("three"));
    assertThat(map.headMap("two", false).values()).containsExactly(3, 5).inOrder();
    assertThat(map.headMap("two", false).descendingMap().values())
        .containsExactly(5, 3).inOrder();
    assertThat(map.descendingKeySet()).containsExactly(
        "two", "three", "one").inOrder();

    assertEquals(mapEntry("one", 3), map.pollFirstEntry());
    assertEquals(mapEntry("two", 3), map.pollLastEntry());
    assertEquals(1, map.size());
  }

  @GwtIncompatible // NavigableMap
  public void testAsMapNavigableReadsThrough() {
    NavigableSet<String> strings = Sets.newTreeSet();
    Collections.addAll(strings, "one", "two", "three");
    NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertNull(map.comparator());
    assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map);
    assertNull(map.get("four"));
    strings.add("four");
    assertEquals(
        ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4),
        map);
    assertEquals(Integer.valueOf(4), map.get("four"));
    SortedMap<String, Integer> headMap = map.headMap("two");
    assertEquals(
        ImmutableSortedMap.of("four", 4, "one", 3, "three", 5),
        headMap);
    strings.add("five");
    strings.remove("one");
    assertEquals(
        ImmutableSortedMap.of("five", 4, "four", 4, "three", 5),
        headMap);
    assertThat(map.entrySet()).containsExactly(
        mapEntry("five", 4),
        mapEntry("four", 4),
        mapEntry("three", 5),
        mapEntry("two", 3)).inOrder();

    NavigableMap<String, Integer> tailMap = map.tailMap("s", true);
    NavigableMap<String, Integer> subMap = map.subMap("a", true, "t", false);

    strings.add("six");
    strings.remove("two");
    assertThat(tailMap.entrySet()).containsExactly(
        mapEntry("six", 3),
        mapEntry("three", 5)).inOrder();
    assertThat(subMap.entrySet()).containsExactly(
        mapEntry("five", 4),
        mapEntry("four", 4),
        mapEntry("six", 3)).inOrder();
  }

  @GwtIncompatible // NavigableMap
  public void testAsMapNavigableWritesThrough() {
    NavigableSet<String> strings = Sets.newTreeSet();
    Collections.addAll(strings, "one", "two", "three");
    NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertEquals(Integer.valueOf(3), map.remove("two"));
    assertThat(strings).containsExactly("one", "three").inOrder();
    assertEquals(mapEntry("three", 5),
        map.subMap("one", false, "zzz", true).pollLastEntry());
    assertThat(strings).contains("one");
  }

  @GwtIncompatible // NavigableMap
  public void testAsMapNavigableSubViewKeySetsDoNotSupportAdd() {
    NavigableMap<String, Integer> map = Maps.asMap(
        Sets.<String>newTreeSet(), LENGTH_FUNCTION);
    try {
      map.descendingKeySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.subMap("a", true, "z", false).keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.tailMap("a", true).keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.headMap("r", true).keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
    try {
      map.headMap("r", false).tailMap("m", true).keySet().add("a");
      fail();
    } catch (UnsupportedOperationException expected) {
    }
  }

  @GwtIncompatible // NavigableMap
  public void testAsMapNavigableEmpty() {
    NavigableSet<String> strings = ImmutableSortedSet.of();
    NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION);
    assertThat(map.entrySet()).isEmpty();
    assertTrue(map.isEmpty());
    assertNull(map.get("five"));
  }

  public void testToMap() {
    Iterable<String> strings = ImmutableList.of("one", "two", "three");
    ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("two", 3),
        mapEntry("three", 5)).inOrder();
  }

  public void testToMapIterator() {
    Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator();
    ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("two", 3),
        mapEntry("three", 5)).inOrder();
  }

  public void testToMapWithDuplicateKeys() {
    Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one");
    ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION);
    assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map);
    assertThat(map.entrySet()).containsExactly(
        mapEntry("one", 3),
        mapEntry("two", 3),
        mapEntry("three", 5)).inOrder();
  }

  public void testToMapWithNullKeys() {
    Iterable<String> strings = Arrays.asList("one", null, "three");
    try {
      Maps.toMap(strings, Functions.constant("foo"));
      fail();
    } catch (NullPointerException expected) {
    }
  }

  public void testToMapWithNullValues() {
    Iterable<String> strings = ImmutableList.of("one", "two", "three");
    try {
      Maps.toMap(strings, Functions.constant(null));
      fail();
    } catch (NullPointerException expected) {
    }
  }

  private static final BiMap<Integer, String> INT_TO_STRING_MAP =
      new ImmutableBiMap.Builder<Integer, String>()
          .put(1, "one")
          .put(2, "two")
          .put(3, "three")
          .build();

  public void testUniqueIndexCollection() {
    ImmutableMap<Integer, String> outputMap =
        Maps.uniqueIndex(INT_TO_STRING_MAP.values(),
            Functions.forMap(INT_TO_STRING_MAP.inverse()));
    assertEquals(INT_TO_STRING_MAP, outputMap);
  }

  public void testUniqueIndexIterable() {
    ImmutableMap<Integer, String> outputMap =
        Maps.uniqueIndex(new Iterable<String>() {
          @Override
          public Iterator<String> iterator() {
            return INT_TO_STRING_MAP.values().iterator();
          }
        },
        Functions.forMap(INT_TO_STRING_MAP.inverse()));
    assertEquals(INT_TO_STRING_MAP, outputMap);
  }

  public void testUniqueIndexIterator() {
    ImmutableMap<Integer, String> outputMap =
        Maps.uniqueIndex(INT_TO_STRING_MAP.values().iterator(),
            Functions.forMap(INT_TO_STRING_MAP.inverse()));
    assertEquals(INT_TO_STRING_MAP, outputMap);
  }

  /** Can't create the map if more than one value maps to the same key. */
  public void testUniqueIndexDuplicates() {
    try {
      Map<Integer, String> unused =
          Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1));
      fail();
    } catch (IllegalArgumentException expected) {
      assertThat(expected.getMessage()).contains("Multimaps.index");
    }
  }

  /** Null values are not allowed. */
  public void testUniqueIndexNullValue() {
    List<String> listWithNull = Lists.newArrayList((String) null);
    try {
      Maps.uniqueIndex(listWithNull, Functions.constant(1));
      fail();
    } catch (NullPointerException expected) {
    }
  }

  /** Null keys aren't allowed either. */
  public void testUniqueIndexNullKey() {
    List<String> oneStringList = Lists.newArrayList("foo");
    try {
      Maps.uniqueIndex(oneStringList, Functions.constant(null));
      fail();
    } catch (NullPointerException expected) {
    }
  }

  @GwtIncompatible // Maps.fromProperties
  @SuppressWarnings("deprecation") // StringBufferInputStream
  public void testFromProperties() throws IOException {
    Properties testProp = new Properties();

    Map<String, String> result = Maps.fromProperties(testProp);
    assertTrue(result.isEmpty());
    testProp.setProperty("first", "true");

    result = Maps.fromProperties(testProp);
    assertEquals("true", result.get("first"));
    assertEquals(1, result.size());
    testProp.setProperty("second", "null");

    result = Maps.fromProperties(testProp);
    assertEquals("true", result.get("first"));
    assertEquals("null", result.get("second"));
    assertEquals(2, result.size());

    // Now test values loaded from a stream.
    String props = "test\n second = 2\n Third item :   a short  phrase   ";

    testProp.load(new StringReader(props));

    result = Maps.fromProperties(testProp);
    assertEquals(4, result.size());
    assertEquals("true", result.get("first"));
    assertEquals("", result.get("test"));
    assertEquals("2", result.get("second"));
    assertEquals("item :   a short  phrase   ", result.get("Third"));
    assertFalse(result.containsKey("not here"));

    // Test loading system properties
    result = Maps.fromProperties(System.getProperties());
    assertTrue(result.containsKey("java.version"));

    // Test that defaults work, too.
    testProp = new Properties(System.getProperties());
    String override = "test\njava.version : hidden";

    testProp.load(new StringReader(override));

    result = Maps.fromProperties(testProp);
    assertTrue(result.size() > 2);
    assertEquals("", result.get("test"));
    assertEquals("hidden", result.get("java.version"));
    assertNotSame(System.getProperty("java.version"),
                  result.get("java.version"));
  }

  @GwtIncompatible // Maps.fromProperties
  @SuppressWarnings("serial") // never serialized
  public void testFromPropertiesNullKey() {
    Properties properties = new Properties() {
      @Override public Enumeration<?> propertyNames() {
        return Iterators.asEnumeration(
            Arrays.asList(null, "first", "second").iterator());
      }
    };
    properties.setProperty("first", "true");
    properties.setProperty("second", "null");

    try {
      Maps.fromProperties(properties);
      fail();
    } catch (NullPointerException expected) {}
  }

  @GwtIncompatible // Maps.fromProperties
  @SuppressWarnings("serial") // never serialized
  public void testFromPropertiesNonStringKeys() {
    Properties properties = new Properties() {
      @Override public Enumeration<?> propertyNames() {
        return Iterators.asEnumeration(
            Arrays.<Object>asList(Integer.valueOf(123), "first").iterator());
      }
    };

    try {
      Maps.fromProperties(properties);
      fail();
    } catch (ClassCastException expected) {}
  }

  public void testAsConverter_nominal() throws Exception {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    for (Entry<String, Integer> entry : biMap.entrySet()) {
      assertSame(entry.getValue(), converter.convert(entry.getKey()));
    }
  }

  public void testAsConverter_inverse() throws Exception {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    for (Entry<String, Integer> entry : biMap.entrySet()) {
      assertSame(entry.getKey(), converter.reverse().convert(entry.getValue()));
    }
  }

  public void testAsConverter_noMapping() throws Exception {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    try {
      converter.convert("three");
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testAsConverter_nullConversions() throws Exception {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    assertNull(converter.convert(null));
    assertNull(converter.reverse().convert(null));
  }

  public void testAsConverter_isAView() throws Exception {
    BiMap<String, Integer> biMap = HashBiMap.create();
    biMap.put("one", 1);
    biMap.put("two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);

    assertSame(1, converter.convert("one"));
    assertSame(2, converter.convert("two"));
    try {
      converter.convert("three");
      fail();
    } catch (IllegalArgumentException expected) {
    }

    biMap.put("three", 3);

    assertSame(1, converter.convert("one"));
    assertSame(2, converter.convert("two"));
    assertSame(3, converter.convert("three"));
  }

  public void testAsConverter_withNullMapping() throws Exception {
    BiMap<String, Integer> biMap = HashBiMap.create();
    biMap.put("one", 1);
    biMap.put("two", 2);
    biMap.put("three", null);
    try {
      Maps.asConverter(biMap).convert("three");
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  public void testAsConverter_toString() {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    assertEquals("Maps.asConverter({one=1, two=2})", converter.toString());
  }

  public void testAsConverter_serialization() {
    ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of(
        "one", 1,
        "two", 2);
    Converter<String, Integer> converter = Maps.asConverter(biMap);
    SerializableTester.reserializeAndAssert(converter);
  }

  public void testUnmodifiableBiMap() {
    BiMap<Integer, String> mod = HashBiMap.create();
    mod.put(1, "one");
    mod.put(2, "two");
    mod.put(3, "three");

    BiMap<Number, String> unmod = Maps.unmodifiableBiMap(mod);

    /* No aliasing on inverse operations. */
    assertSame(unmod.inverse(), unmod.inverse());
    assertSame(unmod, unmod.inverse().inverse());

    /* Unmodifiable is a view. */
    mod.put(4, "four");
    assertEquals(true, unmod.get(4).equals("four"));
    assertEquals(true, unmod.inverse().get("four").equals(4));

    /* UnsupportedOperationException on direct modifications. */
    try {
      unmod.put(4, "four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    try {
      unmod.forcePut(4, "four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    try {
      unmod.putAll(Collections.singletonMap(4, "four"));
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}

    /* UnsupportedOperationException on indirect modifications. */
    BiMap<String, Number> inverse = unmod.inverse();
    try {
      inverse.put("four", 4);
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    try {
      inverse.forcePut("four", 4);
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    try {
      inverse.putAll(Collections.singletonMap("four", 4));
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    Set<String> values = unmod.values();
    try {
      values.remove("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    Set<Map.Entry entries = unmod.entrySet();
    Map.Entry<Number, String> entry = entries.iterator().next();
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    @SuppressWarnings("unchecked")
    Map.Entry<Integer, String> entry2
        = (Map.Entry<Integer, String>) entries.toArray()[0];
    try {
      entry2.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
  }

  public void testImmutableEntry() {
    Map.Entry<String, Integer> e = Maps.immutableEntry("foo", 1);
    assertEquals("foo", e.getKey());
    assertEquals(1, (int) e.getValue());
    try {
      e.setValue(2);
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    assertEquals("foo=1", e.toString());
    assertEquals(101575, e.hashCode());
  }

  public void testImmutableEntryNull() {
    Map.Entry<String, Integer> e
        = Maps.immutableEntry((String) null, (Integer) null);
    assertNull(e.getKey());
    assertNull(e.getValue());
    try {
      e.setValue(null);
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {}
    assertEquals("null=null", e.toString());
    assertEquals(0, e.hashCode());
  }

  /** See {@link SynchronizedBiMapTest} for more tests. */
  public void testSynchronizedBiMap() {
    BiMap<String, Integer> bimap = HashBiMap.create();
    bimap.put("one", 1);
    BiMap<String, Integer> sync = Maps.synchronizedBiMap(bimap);
    bimap.put("two", 2);
    sync.put("three", 3);
    assertEquals(ImmutableSet.of(1, 2, 3), bimap.inverse().keySet());
    assertEquals(ImmutableSet.of(1, 2, 3), sync.inverse().keySet());
  }

  private static final Predicate<String> NOT_LENGTH_3
      = new Predicate<String>() {
        @Override
        public boolean apply(String input) {
          return input == null || input.length() != 3;
        }
      };

  private static final Predicate<Integer> EVEN
      = new Predicate<Integer>() {
        @Override
        public boolean apply(Integer input) {
          return input == null || input % 2 == 0;
        }
      };

  private static final Predicate<Entry CORRECT_LENGTH
      = new Predicate<Entry() {
        @Override
        public boolean apply(Entry<String, Integer> input) {
          return input.getKey().length() == input.getValue();
        }
      };

  private static final Function<Integer, Double> SQRT_FUNCTION = new Function() {
      @Override
      public Double apply(Integer in) {
        return Math.sqrt(in);
      }
    };

  public static class FilteredMapTest extends TestCase {
    Map<String, Integer> createUnfiltered() {
      return Maps.newHashMap();
    }

    public void testFilteredKeysIllegalPut() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
      filtered.put("a", 1);
      filtered.put("b", 2);
      assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);

      try {
        filtered.put("yyy", 3);
        fail();
      } catch (IllegalArgumentException expected) {}
    }

    public void testFilteredKeysIllegalPutAll() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
      filtered.put("a", 1);
      filtered.put("b", 2);
      assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);

      try {
        filtered.putAll(ImmutableMap.of("c", 3, "zzz", 4, "b", 5));
        fail();
      } catch (IllegalArgumentException expected) {}

      assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered);
    }

    public void testFilteredKeysFilteredReflectsBackingChanges() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3);
      unfiltered.put("two", 2);
      unfiltered.put("three", 3);
      unfiltered.put("four", 4);
      assertEquals(ImmutableMap.of("two", 2, "three", 3, "four", 4), unfiltered);
      assertEquals(ImmutableMap.of("three", 3, "four", 4), filtered);

      unfiltered.remove("three");
      assertEquals(ImmutableMap.of("two", 2, "four", 4), unfiltered);
      assertEquals(ImmutableMap.of("four", 4), filtered);

      unfiltered.clear();
      assertEquals(ImmutableMap.of(), unfiltered);
      assertEquals(ImmutableMap.of(), filtered);
    }

    public void testFilteredValuesIllegalPut() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
      filtered.put("a", 2);
      unfiltered.put("b", 4);
      unfiltered.put("c", 5);
      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);

      try {
        filtered.put("yyy", 3);
        fail();
      } catch (IllegalArgumentException expected) {}
      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
    }

    public void testFilteredValuesIllegalPutAll() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
      filtered.put("a", 2);
      unfiltered.put("b", 4);
      unfiltered.put("c", 5);
      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);

      try {
        filtered.putAll(ImmutableMap.of("c", 4, "zzz", 5, "b", 6));
        fail();
      } catch (IllegalArgumentException expected) {}
      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
    }

    public void testFilteredValuesIllegalSetValue() {
      Map<String, Integer> unfiltered = createUnfiltered();
      Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
      filtered.put("a", 2);
      filtered.put("b", 4);
      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);

      Entry<String, Integer> entry = filtered.entrySet().iterator().next();
      try {
        entry.setValue(5);
        fail();
      } catch (IllegalArgumentException expected) {}

      assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered);
    }

    public void testFilteredValuesClear() {
      Map<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("one", 1);
      unfiltered.put("two", 2);
      unfiltered.put("three", 3);
      unfiltered.put("four", 4);
      Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN);
      assertEquals(ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4),
          unfiltered);
      assertEquals(ImmutableMap.of("two", 2, "four", 4), filtered);

      filtered.clear();
      assertEquals(ImmutableMap.of("one", 1, "three", 3), unfiltered);
      assertTrue(filtered.isEmpty());
    }

    public void testFilteredEntriesIllegalPut() {
      Map<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("cat", 3);
      unfiltered.put("dog", 2);
      unfiltered.put("horse", 5);
      Map<String, Integer> filtered
          = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered);

      filtered.put("chicken", 7);
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);

      try {
        filtered.put("cow", 7);
        fail();
      } catch (IllegalArgumentException expected) {}
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
    }

    public void testFilteredEntriesIllegalPutAll() {
      Map<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("cat", 3);
      unfiltered.put("dog", 2);
      unfiltered.put("horse", 5);
      Map<String, Integer> filtered
          = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered);

      filtered.put("chicken", 7);
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);

      try {
        filtered.putAll(ImmutableMap.of("sheep", 5, "cow", 7));
        fail();
      } catch (IllegalArgumentException expected) {}
      assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered);
    }

    public void testFilteredEntriesObjectPredicate() {
      Map<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("cat", 3);
      unfiltered.put("dog", 2);
      unfiltered.put("horse", 5);
      Predicate<Object> predicate = Predicates.alwaysFalse();
      Map<String, Integer> filtered
          = Maps.filterEntries(unfiltered, predicate);
      assertTrue(filtered.isEmpty());
    }

    public void testFilteredEntriesWildCardEntryPredicate() {
      Map<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("cat", 3);
      unfiltered.put("dog", 2);
      unfiltered.put("horse", 5);
      Predicate<Entry predicate = new Predicate>() {
        @Override
        public boolean apply(Entry<?, ?> input) {
          return "cat".equals(input.getKey())
              || Integer.valueOf(2) == input.getValue();
        }
      };
      Map<String, Integer> filtered
          = Maps.filterEntries(unfiltered, predicate);
      assertEquals(ImmutableMap.of("cat", 3, "dog", 2), filtered);
    }
  }

  public static class FilteredSortedMapTest extends FilteredMapTest {
    @Override
    SortedMap<String, Integer> createUnfiltered() {
      return Maps.newTreeMap();
    }

    public void testFirstAndLastKeyFilteredMap() {
      SortedMap<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("apple", 2);
      unfiltered.put("banana", 6);
      unfiltered.put("cat", 3);
      unfiltered.put("dog", 5);

      SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH);
      assertEquals("banana", filtered.firstKey());
      assertEquals("cat", filtered.lastKey());
    }

    public void testHeadSubTailMap_FilteredMap() {
      SortedMap<String, Integer> unfiltered = createUnfiltered();
      unfiltered.put("apple", 2);
      unfiltered.put("banana", 6);
      unfiltered.put("cat", 4);
      unfiltered.put("dog", 3);
      SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH);

      assertEquals(ImmutableMap.of("banana", 6), filtered.headMap("dog"));
      assertEquals(ImmutableMap.of(), filtered.headMap("banana"));
      assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.headMap("emu"));

      assertEquals(ImmutableMap.of("banana", 6), filtered.subMap("banana", "dog"));
      assertEquals(ImmutableMap.of("dog", 3), filtered.subMap("cat", "emu"));

      assertEquals(ImmutableMap.of("dog", 3), filtered.tailMap("cat"));
      assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.tailMap("banana"));
    }
  }

  public static class FilteredBiMapTest extends FilteredMapTest {
    @Override
    BiMap<String, Integer> createUnfiltered() {
      return HashBiMap.create();
    }
  }

  public void testTransformValues() {
    Map<String, Integer> map = ImmutableMap.of("a", 4, "b", 9);
    Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION);

    assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed);
  }

  public void testTransformEntries() {
    Map<String, String> map = ImmutableMap.of("a", "4", "b", "9");
    EntryTransformer<String, String, String> concat =
        new EntryTransformer<String, String, String>() {
          @Override
          public String transformEntry(String key, String value) {
            return key + value;
          }
        };
    Map<String, String> transformed = transformEntries(map, concat);

    assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed);
  }

  @SuppressWarnings("unused")
  public void testTransformEntriesGenerics() {
    Map<Object, Object> map1 = ImmutableMap.of(1, 2);
    Map<Object, Number> map2 = ImmutableMap.of(1, 2);
    Map<Object, Integer> map3 = ImmutableMap.of(1, 2);
    Map<Number, Object> map4 = ImmutableMap.of(1, 2);
    Map<Number, Number> map5 = ImmutableMap.of(1, 2);
    Map<Number, Integer> map6 = ImmutableMap.of(1, 2);
    Map<Integer, Object> map7 = ImmutableMap.of(1, 2);
    Map<Integer, Number> map8 = ImmutableMap.of(1, 2);
    Map<Integer, Integer> map9 = ImmutableMap.of(1, 2);
    Map<? extends Number, ? extends Number> map0 = ImmutableMap.of(1, 2);

    EntryTransformer<Number, Number, Double> transformer =
        new EntryTransformer<Number, Number, Double>() {
          @Override
          public Double transformEntry(Number key, Number value) {
            return key.doubleValue() + value.doubleValue();
          }
        };

    Map<Object, Double> objectKeyed;
    Map<Number, Double> numberKeyed;
    Map<Integer, Double> integerKeyed;

    numberKeyed = transformEntries(map5, transformer);
    numberKeyed = transformEntries(map6, transformer);
    integerKeyed = transformEntries(map8, transformer);
    integerKeyed = transformEntries(map9, transformer);

    Map<? extends Number, Double> wildcarded = transformEntries(map0, transformer);

    // Can't loosen the key type:
    // objectKeyed = transformEntries(map5, transformer);
    // objectKeyed = transformEntries(map6, transformer);
    // objectKeyed = transformEntries(map8, transformer);
    // objectKeyed = transformEntries(map9, transformer);
    // numberKeyed = transformEntries(map8, transformer);
    // numberKeyed = transformEntries(map9, transformer);

    // Can't loosen the value type:
    // Map<Number, Number> looseValued1 = transformEntries(map5, transformer);
    // Map<Number, Number> looseValued2 = transformEntries(map6, transformer);
    // Map<Integer, Number> looseValued3 = transformEntries(map8, transformer);
    // Map<Integer, Number> looseValued4 = transformEntries(map9, transformer);

    // Can't call with too loose a key:
    // transformEntries(map1, transformer);
    // transformEntries(map2, transformer);
    // transformEntries(map3, transformer);

    // Can't call with too loose a value:
    // transformEntries(map1, transformer);
    // transformEntries(map4, transformer);
    // transformEntries(map7, transformer);
  }

  public void testTransformEntriesExample() {
    Map<String, Boolean> options =
        ImmutableMap.of("verbose", true, "sort", false);
    EntryTransformer<String, Boolean, String> flagPrefixer =
        new EntryTransformer<String, Boolean, String>() {
          @Override
          public String transformEntry(String key, Boolean value) {
            return value ? key : "no" + key;
          }
        };
    Map<String, String> transformed = transformEntries(options, flagPrefixer);
    assertEquals("{verbose=verbose, sort=nosort}", transformed.toString());
  }

  // Logically this would accept a NavigableMap, but that won't work under GWT.
  private static <K, V> SortedMap sortedNotNavigable(
      final SortedMap<K, V> map) {
    return new ForwardingSortedMap<K, V>() {
      @Override protected SortedMap<K, V> delegate() {
        return map;
      }
    };
  }

  public void testSortedMapTransformValues() {
    SortedMap<String, Integer> map =
        sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9));
    SortedMap<String, Double> transformed =
        transformValues(map, SQRT_FUNCTION);

    /*
     * We'd like to sanity check that we didn't get a NavigableMap out, but we
     * can't easily do so while maintaining GWT compatibility.
     */
    assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed);
  }

  @GwtIncompatible // NavigableMap
  public void testNavigableMapTransformValues() {
    NavigableMap<String, Integer> map = ImmutableSortedMap.of("a", 4, "b", 9);
    NavigableMap<String, Double> transformed =
        transformValues(map, SQRT_FUNCTION);

    assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed);
  }

  public void testSortedMapTransformEntries() {
    SortedMap<String, String> map =
        sortedNotNavigable(ImmutableSortedMap.of("a", "4", "b", "9"));
    EntryTransformer<String, String, String> concat =
        new EntryTransformer<String, String, String>() {
          @Override
          public String transformEntry(String key, String value) {
            return key + value;
          }
        };
    SortedMap<String, String> transformed = transformEntries(map, concat);

    /*
     * We'd like to sanity check that we didn't get a NavigableMap out, but we
     * can't easily do so while maintaining GWT compatibility.
     */
    assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed);
  }

  @GwtIncompatible // NavigableMap
  public void testNavigableMapTransformEntries() {
    NavigableMap<String, String> map =
        ImmutableSortedMap.of("a", "4", "b", "9");
    EntryTransformer<String, String, String> concat =
        new EntryTransformer<String, String, String>() {
          @Override
          public String transformEntry(String key, String value) {
            return key + value;
          }
        };
    NavigableMap<String, String> transformed = transformEntries(map, concat);

    assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed);
  }

  @GwtIncompatible // NavigableMap
  public void testUnmodifiableNavigableMap() {
    TreeMap<Integer, String> mod = Maps.newTreeMap();
    mod.put(1, "one");
    mod.put(2, "two");
    mod.put(3, "three");

    NavigableMap<Integer, String> unmod = unmodifiableNavigableMap(mod);

    /* unmod is a view. */
    mod.put(4, "four");
    assertEquals("four", unmod.get(4));
    assertEquals("four", unmod.descendingMap().get(4));

    ensureNotDirectlyModifiable(unmod);
    ensureNotDirectlyModifiable(unmod.descendingMap());
    ensureNotDirectlyModifiable(unmod.headMap(2, true));
    ensureNotDirectlyModifiable(unmod.subMap(1, true, 3, true));
    ensureNotDirectlyModifiable(unmod.tailMap(2, true));

    Collection<String> values = unmod.values();
    try {
      values.add("4");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      values.remove("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      values.removeAll(Collections.singleton("four"));
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      values.retainAll(Collections.singleton("four"));
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      Iterator<String> iterator = values.iterator();
      iterator.next();
      iterator.remove();
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }

    Set<Map.Entry entries = unmod.entrySet();
    try {
      Iterator<Map.Entry iterator = entries.iterator();
      iterator.next();
      iterator.remove();
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    Map.Entry<Integer, String> entry = entries.iterator().next();
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.lowerEntry(1);
    assertNull(entry);
    entry = unmod.floorEntry(2);
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.ceilingEntry(2);
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.lowerEntry(2);
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.higherEntry(2);
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.firstEntry();
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    entry = unmod.lastEntry();
    try {
      entry.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
        @SuppressWarnings("unchecked")
    Map.Entry<Integer, String> entry2 =
        (Map.Entry<Integer, String>) entries.toArray()[0];
    try {
      entry2.setValue("four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
  }

  @GwtIncompatible // NavigableMap
  void ensureNotDirectlyModifiable(NavigableMap<Integer, String> unmod) {
    try {
      unmod.put(4, "four");
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      unmod.putAll(Collections.singletonMap(4, "four"));
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      unmod.remove(4);
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      unmod.pollFirstEntry();
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
    try {
      unmod.pollLastEntry();
      fail("UnsupportedOperationException expected");
    } catch (UnsupportedOperationException expected) {
    }
  }

  @GwtIncompatible // NavigableMap
  public void testSubMap_boundedRange() {
    ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0);
    ImmutableSortedMap<Integer, Integer> empty = ImmutableSortedMap.of();

    assertEquals(map, Maps.subMap(map, Range.closed(0, 12)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.closed(0, 4)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.closed(2, 6)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.closed(3, 7)));
    assertEquals(empty, Maps.subMap(map, Range.closed(20, 30)));

    assertEquals(map, Maps.subMap(map, Range.open(0, 12)));
    assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.open(0, 4)));
    assertEquals(ImmutableSortedMap.of(4, 0), Maps.subMap(map, Range.open(2, 6)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.open(3, 7)));
    assertEquals(empty, Maps.subMap(map, Range.open(20, 30)));

    assertEquals(map, Maps.subMap(map, Range.openClosed(0, 12)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.openClosed(0, 4)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.openClosed(2, 6)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.openClosed(3, 7)));
    assertEquals(empty, Maps.subMap(map, Range.openClosed(20, 30)));

    assertEquals(map, Maps.subMap(map, Range.closedOpen(0, 12)));
    assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.closedOpen(0, 4)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.closedOpen(2, 6)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0), Maps.subMap(map, Range.closedOpen(3, 7)));
    assertEquals(empty, Maps.subMap(map, Range.closedOpen(20, 30)));
  }

  @GwtIncompatible // NavigableMap
  public void testSubMap_halfBoundedRange() {
    ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0);
    ImmutableSortedMap<Integer, Integer> empty = ImmutableSortedMap.of();

    assertEquals(map, Maps.subMap(map, Range.atLeast(0)));
    assertEquals(ImmutableSortedMap.of(4, 0, 6, 0, 8, 0, 10, 0),
        Maps.subMap(map, Range.atLeast(4)));
    assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.atLeast(7)));
    assertEquals(empty, Maps.subMap(map, Range.atLeast(20)));

    assertEquals(map, Maps.subMap(map, Range.greaterThan(0)));
    assertEquals(ImmutableSortedMap.of(6, 0, 8, 0, 10, 0), Maps.subMap(map, Range.greaterThan(4)));
    assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.greaterThan(7)));
    assertEquals(empty, Maps.subMap(map, Range.greaterThan(20)));

    assertEquals(empty, Maps.subMap(map, Range.lessThan(0)));
    assertEquals(ImmutableSortedMap.of(2, 0), Maps.subMap(map, Range.lessThan(4)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.lessThan(7)));
    assertEquals(map, Maps.subMap(map, Range.lessThan(20)));

    assertEquals(empty, Maps.subMap(map, Range.atMost(0)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.atMost(4)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0), Maps.subMap(map, Range.atMost(7)));
    assertEquals(map, Maps.subMap(map, Range.atMost(20)));
  }

  @GwtIncompatible // NavigableMap
  public void testSubMap_unboundedRange() {
    ImmutableSortedMap<Integer, Integer> map = ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0);

    assertEquals(map, Maps.subMap(map, Range.<Integer>all()));
  }

  @GwtIncompatible // NavigableMap
  public void testSubMap_unnaturalOrdering() {
    ImmutableSortedMap<Integer, Integer> map =
        ImmutableSortedMap.<Integer, Integer>reverseOrder()
            .put(2, 0).put(4, 0).put(6, 0).put(8, 0).put(10, 0).build();

    try {
      Maps.subMap(map, Range.closed(4, 8));
      fail("IllegalArgumentException expected");
    } catch (IllegalArgumentException expected) {
    }

    // These results are all incorrect, but there's no way (short of iterating over the result)
    // to verify that with an arbitrary ordering or comparator.
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0), Maps.subMap(map, Range.atLeast(4)));
    assertEquals(ImmutableSortedMap.of(8, 0, 10, 0), Maps.subMap(map, Range.atMost(8)));
    assertEquals(ImmutableSortedMap.of(2, 0, 4, 0, 6, 0, 8, 0, 10, 0),
        Maps.subMap(map, Range.<Integer>all()));
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java MapsTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.