public static <T> Set<T> intersect(final Set<? extends T> set1, final Set<? extends T> set2) {
    if (set1.equals(set2)){
      return (Set<T>)set1;
    }
    Set<T> result = new HashSet<>();
    Set<? extends T> minSet;
    Set<? extends T> otherSet;
    if (set1.size() < set2.size()){
      minSet = set1;
      otherSet = set2;
    } else {
      minSet = set2;
      otherSet = set1;
    }
    for (T s : minSet) {
      if (otherSet.contains(s)){
        result.add(s);
      }
    }
    return result;
  }
public static <T> Set<T> intersect(final Set<? extends T> set1, final Set<? extends T> set2)