@Override
  public final void isEqualTo(@Nullable Object other) {
    @SuppressWarnings("UndefinedEquals") // the contract of this method is to follow Multimap.equals
    boolean isEqual = Objects.equal(actual, other);
    if (isEqual) {
      return;
    }

    // Fail but with a more descriptive message:
    if ((actual instanceof ListMultimap && other instanceof SetMultimap)
        || (actual instanceof SetMultimap && other instanceof ListMultimap)) {
      String actualType = (actual instanceof ListMultimap) ? "ListMultimap" : "SetMultimap";
      String otherType = (other instanceof ListMultimap) ? "ListMultimap" : "SetMultimap";
      failWithoutActual(
          fact("expected", other),
          fact("an instance of", otherType),
          fact("but was", actualCustomStringRepresentationForPackageMembersToCall()),
          fact("an instance of", actualType),
          simpleFact(
              lenientFormat(
                  "a %s cannot equal a %s if either is non-empty", actualType, otherType)));
    } else if (actual instanceof ListMultimap) {
      containsExactlyEntriesIn((Multimap<?, ?>) checkNotNull(other)).inOrder();
    } else if (actual instanceof SetMultimap) {
      containsExactlyEntriesIn((Multimap<?, ?>) checkNotNull(other));
    } else {
      super.isEqualTo(other);
    }
  }
@Test
  public void setMultimapIsEqualTo_passes() {
    ImmutableSetMultimap<String, String> multimapA =
        ImmutableSetMultimap.<String, String>builder()
            .putAll("kurt", "kluever", "russell", "cobain")
            .build();
    ImmutableSetMultimap<String, String> multimapB =
        ImmutableSetMultimap.<String, String>builder()
            .putAll("kurt", "kluever", "cobain", "russell")
            .build();

    assertThat(multimapA.equals(multimapB)).isTrue();

    assertThat(multimapA).isEqualTo(multimapB);
  }