android/guava/src/com/google/common/collect/Sets.java
public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
    checkNotNull(set1, "set1");
    checkNotNull(set2, "set2");

    return new SetView<E>() {
      @Override
      public int size() {
        int size = set1.size();
        for (E e : set2) {
          if (!set1.contains(e)) {
            size++;
          }
        }
        return size;
      }

      @Override
      public boolean isEmpty() {
        return set1.isEmpty() && set2.isEmpty();
      }

      @Override
      public UnmodifiableIterator<E> iterator() {
        return new AbstractIterator<E>() {
          final Iterator<? extends E> itr1 = set1.iterator();
          final Iterator<? extends E> itr2 = set2.iterator();

          @Override
          protected E computeNext() {
            if (itr1.hasNext()) {
              return itr1.next();
            }
            while (itr2.hasNext()) {
              E e = itr2.next();
              if (!set1.contains(e)) {
                return e;
              }
            }
            return endOfData();
          }
        };
      }

      @Override
      public boolean contains(Object object) {
        return set1.contains(object) || set2.contains(object);
      }

      @Override
      public <S extends Set<E>> S copyInto(S set) {
        set.addAll(set1);
        set.addAll(set2);
        return set;
      }

      @Override
      public ImmutableSet<E> immutableCopy() {
        return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
      }
    };
  }
public static <E> SetView<E> union(final Set<? extends E> set1, final Set<? extends E> set2) {
    checkNotNull(set1, "set1");
    checkNotNull(set2, "set2");

    return new SetView<E>() {
      @Override
      public int size() {
        int size = set1.size();
        for (E e : set2) {
          if (!set1.contains(e)) {
            size++;
          }
        }
        return size;
      }

      @Override
      public boolean isEmpty() {
        return set1.isEmpty() && set2.isEmpty();
      }

      @Override
      public UnmodifiableIterator<E> iterator() {
        return new AbstractIterator<E>() {
          final Iterator<? extends E> itr1 = set1.iterator();
          final Iterator<? extends E> itr2 = set2.iterator();

          @Override
          protected E computeNext() {
            if (itr1.hasNext()) {
              return itr1.next();
            }
            while (itr2.hasNext()) {
              E e = itr2.next();
              if (!set1.contains(e)) {
                return e;
              }
            }
            return endOfData();
          }
        };
      }

      @Override
      public boolean contains(Object object) {
        return set1.contains(object) || set2.contains(object);
      }

      @Override
      public <S extends Set<E>> S copyInto(S set) {
        set.addAll(set1);
        set.addAll(set2);
        return set;
      }

      @Override
      public ImmutableSet<E> immutableCopy() {
        return new ImmutableSet.Builder<E>().addAll(set1).addAll(set2).build();
      }
    };
  }
public static < E > SetView < E > union ( final Set < ? extends E > set1 , final Set < ? extends E > set2 ) { checkNotNull ( set1 , "set1" ) ; checkNotNull ( set2 , "set2" ) ; return new SetView < E > ( ) { @ Override public int size ( ) { int size = set1 . size ( ) ; for ( E e : set2 ) { if ( ! set1 . contains ( e ) ) { size ++ ; } } return size ; } @ Override public boolean isEmpty ( ) { return set1 . isEmpty ( ) && set2 . isEmpty ( ) ; } @ Override public UnmodifiableIterator < E > iterator ( ) { return new AbstractIterator < E > ( ) { final Iterator < ? extends E > itr1 = set1 . iterator ( ) ; final Iterator < ? extends E > itr2 = set2 . iterator ( ) ; @ Override protected E computeNext ( ) { if ( itr1 . hasNext ( ) ) { return itr1 . next ( ) ; } while ( itr2 . hasNext ( ) ) { E e = itr2 . next ( ) ; if ( ! set1 . contains ( e ) ) { return e ; } } return endOfData ( ) ; } } ; } @ Override public boolean contains ( Object object ) { return set1 . contains ( object ) || set2 . contains ( object ) ; } @ Override public < S extends Set < E > > S copyInto ( S set ) { set . addAll ( set1 ) ; set . addAll ( set2 ) ; return set ; } @ Override public ImmutableSet < E > immutableCopy ( ) { return new ImmutableSet . Builder < E > ( ) . addAll ( set1 ) . addAll ( set2 ) . build ( ) ; } } ; }
Returns an unmodifiable <b>view</b> of the union of two sets. The returned set contains all
elements that are contained in either backing set. Iterating over the returned set iterates
first over all the elements of {@code set1}, then over each element of {@code set2}, in order,
that is not contained in {@code set1}.

<p>Results are undefined if {@code set1} and {@code set2} are sets based on different
equivalence relations (as {@link HashSet}, {@link TreeSet}, and the {@link Map#keySet} of an
{@code IdentityHashMap} all are).
Returns an unmodifiable <b > view< / b > of the union of two sets . The returned set contains all elements that are contained in either backing set . Iterating over the returned set iterates first over all the elements of { @code set1 } then over each element of { @code set2 } in order that is not contained in { @code set1 } .