@Override
  @Test
  public void forEachWithIndex() {
    super.forEachWithIndex();

    final UnifiedSet<String> set = UnifiedSet.newSet();

    // map with a chain and no empty slots
    MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(2);
    map.forEachWithIndex(
        new ObjectIntProcedure<Integer>() {
          public void value(Integer each, int index) {
            set.add(index + ":" + each.toString());
          }
        });
    Assert.assertEquals(UnifiedSet.newSetWith("0:0", "1:17"), set);

    set.clear();

    // map with a chain and empty slots
    MutableMap<Integer, Integer> map2 = this.mapWithCollisionsOfSize(5);
    map2.forEachWithIndex(
        new ObjectIntProcedure<Integer>() {
          public void value(Integer each, int index) {
            set.add(index + ":" + each.toString());
          }
        });
    Assert.assertEquals(UnifiedSet.newSetWith("0:0", "1:17", "2:34", "3:51", "4:68"), set);
  }
  @Override
  @Test
  public void retainAllFromEntrySet() {
    super.retainAllFromEntrySet();

    for (int i = 1; i < COLLISIONS.size(); i++) {
      MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(i);

      Assert.assertFalse(
          map.entrySet()
              .retainAll(
                  FastList.newList(map.entrySet())
                      .with(ImmutableEntry.of(COLLISION_10, COLLISION_10))));

      Assert.assertTrue(map.entrySet().retainAll(this.mapWithCollisionsOfSize(i - 1).entrySet()));
      Assert.assertEquals(this.mapWithCollisionsOfSize(i - 1), map);
    }

    // simple map, collection to retain contains non-entry element
    MutableMap<Integer, String> map4 = this.newMapWithKeysValues(1, "One", 2, "Two");
    FastList<Object> toRetain =
        FastList.<Object>newListWith(
            ImmutableEntry.of(1, "One"), "explosion!", ImmutableEntry.of(2, "Two"));
    Assert.assertFalse(map4.entrySet().retainAll(toRetain));
  }
  @Override
  @Test
  public void forEachKey() {
    super.forEachKey();

    final UnifiedSet<String> set = UnifiedSet.newSet(5);

    // map with a chain and empty slots
    MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(5);
    map.forEachKey(
        new Procedure<Integer>() {
          public void value(Integer each) {
            set.add(each.toString());
          }
        });
    Assert.assertEquals(UnifiedSet.newSetWith("0", "17", "34", "51", "68"), set);
  }
  @Override
  @Test
  public void removeFromEntrySet() {
    super.removeFromEntrySet();

    for (int i = 1; i < COLLISIONS.size(); i++) {
      MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(i);

      Integer biggestValue = COLLISIONS.get(i - 1);

      Assert.assertTrue(map.entrySet().remove(ImmutableEntry.of(biggestValue, biggestValue)));
      Assert.assertEquals(this.mapWithCollisionsOfSize(i - 1), map);

      Assert.assertFalse(map.entrySet().remove(ImmutableEntry.of(COLLISION_10, COLLISION_10)));
      Assert.assertEquals(this.mapWithCollisionsOfSize(i - 1), map);

      Assert.assertFalse(map.entrySet().remove(null));
    }
  }
  @Override
  @Test
  public void forEachWith() {
    super.forEachWith();

    for (int i = 1; i < COLLISIONS.size(); i++) {
      MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(i);
      final Object sentinal = new Object();
      final UnifiedSet<Integer> result = UnifiedSet.newSet();
      map.forEachWith(
          new Procedure2<Integer, Object>() {
            public void value(Integer argument1, Object argument2) {
              Assert.assertSame(sentinal, argument2);
              result.add(argument1);
            }
          },
          sentinal);
      Assert.assertEquals(map.keySet(), result);
    }
  }
  @Override
  @Test
  public void equalsAndHashCode() {
    super.equalsAndHashCode();

    for (int i = 1; i < COLLISIONS.size(); i++) {
      MutableMap<Integer, Integer> map = this.mapWithCollisionsOfSize(i);
      Map<Integer, Integer> expectedMap = new HashMap<Integer, Integer>(map);

      Verify.assertEqualsAndHashCode(expectedMap, map);
      MutableMap<Integer, Integer> clone1 = map.clone();
      clone1.put(COLLISION_10, COLLISION_10);
      Verify.assertNotEquals(expectedMap, clone1);
      MutableMap<Integer, Integer> clone2 = map.clone();
      clone2.put(null, null);
      Verify.assertNotEquals(expectedMap, clone2);

      expectedMap.put(null, null);
      Verify.assertNotEquals(expectedMap, map);
      expectedMap.remove(null);

      expectedMap.put(COLLISION_10, COLLISION_10);
      Verify.assertNotEquals(expectedMap, map);
    }

    MutableMap<Integer, Integer> mapA = this.mapWithCollisionsOfSize(3);
    MutableMap<Integer, Integer> mapB = this.mapWithCollisionsOfSize(3);

    // map with a chain, compare the null key (and value) with a non-null key
    mapA.put(null, null);
    mapB.put(42, 84);
    Verify.assertNotEquals(mapA, mapB);
    Verify.assertNotEquals(mapA.hashCode(), mapB.hashCode());

    // map with a chain, compare the two null keys with different values (one null, one not)
    mapB.remove(42);
    mapB.put(null, 42);
    Verify.assertNotEquals(mapA, mapB);

    // map with a chain, compare a non-null key (null value) with a non-null key and value
    mapB.remove(null);
    mapB.remove(42);
    mapA.remove(null);
    mapA.put(17, null);
    Verify.assertNotEquals(mapA, mapB);

    MutableMap<Integer, String> mapC = this.newMapWithKeysValues(1, "One", 2, "Two", null, null);
    MutableMap<Integer, String> mapD = this.newMapWithKeysValues(1, "One", 2, "Two", 3, "Three");

    // compare the null key (and value) with a non-null key
    Verify.assertNotEquals(mapC, mapD);

    // compare a non-null key (and null value) with a non-null key
    mapC.remove(null);
    mapC.put(3, null);
    Verify.assertNotEquals(mapC, mapD);

    // reset
    mapC.remove(3);
    mapC.put(null, null);

    // compare the null key (and null value) with a null key (and non-null value)
    mapD.remove(3);
    mapD.put(null, "Three");

    // compare the two null keys with different values (one null, one not)
    Verify.assertNotEquals(mapC, mapD);

    Assert.assertEquals(0, this.newMapWithKeyValue(null, null).hashCode());
  }