static <T extends DiffCapable<T, D>, D extends Difference> Specifier<T, D> deepDiff(@Nullable Iterable<T> past, @Nullable Iterable<T> now) {
    if (isEmpty(past)) {
      if (isEmpty(now)) {
        return new Specifier<>() {
          @Override
          public boolean unchanged() {
            return true;
          }
        };
      }
      return new Specifier<>() {
        @Override
        public Iterable<T> added() {
          return now;
        }

        @Override
        public boolean unchanged() {
          return false;
        }
      };
    }
    else if (isEmpty(now)) {
      return new Specifier<>() {
        @Override
        public Iterable<T> removed() {
          return past;
        }

        @Override
        public boolean unchanged() {
          return false;
        }
      };
    }

    Set<T> pastSet = collect(past, Containers.createCustomPolicySet(T::isSame, T::diffHashCode));
    Set<T> nowSet = collect(now, Containers.createCustomPolicySet(T::isSame, T::diffHashCode));

    Iterable<T> added = lazy(() -> collect(filter(nowSet, obj -> !pastSet.contains(obj)), new ArrayList<>()));
    Iterable<T> removed = lazy(() -> collect(filter(pastSet, obj -> !nowSet.contains(obj)), new ArrayList<>()));

    Iterable<Change<T, D>> changed = lazy(() -> {
      final Map<T, T> nowMap = Containers.createCustomPolicyMap(T::isSame, T::diffHashCode);
      for (T s : nowSet) {
        if (pastSet.contains(s)) {
          nowMap.put(s, s);
        }
      }
      final List<Change<T, D>> result = new ArrayList<>(0);
      for (T before : pastSet) {
        T after = nowMap.get(before);
        if (after != null) {
          D diff = after.difference(before);
          if (!diff.unchanged()) {
            result.add(Change.create(before, after, diff));
          }
        }
      }
      return result;
    });

    return new Specifier<>() {
      @Override
      public Iterable<T> added() {
        return added;
      }

      @Override
      public Iterable<T> removed() {
        return removed;
      }

      @Override
      public Iterable<Change<T, D>> changed() {
        return changed;
      }
    };
  }
static <T extends DiffCapable<T, D>, D extends Difference> Specifier<T, D> deepDiff(@Nullable Iterable<T> past, @Nullable Iterable<T> now)