code: public static <E> SetView<E> difference(final Set<E> set1, final Set<?> set2) {
      checkNotNull(set1, "set1");
      checkNotNull(set2, "set2");
  
      return new SetView<E>() {
        @Override
        public UnmodifiableIterator<E> iterator() {
          return new AbstractIterator<E>() {
            final Iterator<E> itr = set1.iterator();
  
            @Override
            protected E computeNext() {
              while (itr.hasNext()) {
                E e = itr.next();
                if (!set2.contains(e)) {
                  return e;
                }
              }
              return endOfData();
            }
          };
        }
  
        @Override
        public int size() {
          int size = 0;
          for (E e : set1) {
            if (!set2.contains(e)) {
              size++;
            }
          }
          return size;
        }
  
        @Override
        public boolean isEmpty() {
          return set2.containsAll(set1);
        }
  
        @Override
        public boolean contains(Object element) {
          return set1.contains(element) && !set2.contains(element);
        }
      };
    }
docs: Returns an unmodifiable <b>view</b> of the difference of two sets. The returned set contains
  all elements that are contained by {@code set1} and not contained by {@code set2}. {@code set2}
  may also contain elements not present in {@code set1}; these are simply ignored. The iteration
  order of the returned set matches that of {@code set1}.
  
  <p>Results are undefined if {@code set1} and {@code set2} are sets based on different
  equivalence relations (as {@code HashSet}, {@code TreeSet}, and the keySet of an {@code
  IdentityHashMap} all are).