class FieldByFieldComparator implements Comparator<Object> {

  protected final Map<String, Comparator<?>> comparatorsByPropertyOrField;
  protected final TypeComparators comparatorsByType;

  public FieldByFieldComparator(Map<String, Comparator<?>> comparatorsByPropertyOrField,
                                TypeComparators typeComparators) {
    this.comparatorsByPropertyOrField = comparatorsByPropertyOrField == null
        ? new TreeMap<>()
        : comparatorsByPropertyOrField;
    this.comparatorsByType = isNullOrEmpty(typeComparators) ? defaultTypeComparators() : typeComparators;
  }

  public FieldByFieldComparator() {
    this(new TreeMap<>(), defaultTypeComparators());
  }

  @Override
  public int compare(Object actual, Object other) {<FILL_FUNCTION_BODY>}

  protected boolean areEqual(Object actual, Object other) {
    try {
      return Objects.instance().areEqualToIgnoringGivenFields(actual, other, comparatorsByPropertyOrField,
                                                              comparatorsByType);
    } catch (IntrospectionError e) {
      return false;
    }
  }

  @Override
  public String toString() {
    return description() + describeUsedComparators();
  }

  protected String description() {
    return "field/property by field/property comparator on all fields/properties";
  }

  protected String describeUsedComparators() {
    if (comparatorsByPropertyOrField.isEmpty()) {
      return format("%nComparators used:%n%s", describeFieldComparatorsByType());
    }
    return format("%nComparators used:%n%s%n%s", describeFieldComparatorsByName(), describeFieldComparatorsByType());
  }

  protected String describeFieldComparatorsByType() {
    return format("- for elements fields (by type): %s", comparatorsByType);
  }

  protected String describeFieldComparatorsByName() {
    if (comparatorsByPropertyOrField.isEmpty()) {
      return "";
    }
    List<String> fieldComparatorsDescription = this.comparatorsByPropertyOrField.entrySet().stream()
                                                                                .map(FieldByFieldComparator::formatFieldComparator)
                                                                                .collect(toList());
    return format("- for elements fields (by name): {%s}", join(fieldComparatorsDescription).with(", "));
  }

  private static String formatFieldComparator(Entry<String, Comparator<?>> next) {
    return next.getKey() + " -> " + next.getValue();
  }

  private static boolean isNullOrEmpty(TypeComparators comparatorByType) {
    return comparatorByType == null || comparatorByType.isEmpty();
  }

}

    if (actual == null && other == null) return 0;
    if (actual == null || other == null) return NOT_EQUAL;
    // value returned is not relevant for ordering if objects are not equal.
    return areEqual(actual, other) ? 0 : NOT_EQUAL;
  
<no_super_class>