class HashSparseSet<T> extends AbstractFlowSet<T> {
  protected LinkedHashSet<T> elements;

  public HashSparseSet() {
    @SuppressWarnings("unchecked")
    LinkedHashSet<T> newElements = new LinkedHashSet<T>();
    elements = newElements;
  }

  private HashSparseSet(HashSparseSet<T> other) {
    elements = new LinkedHashSet<T>(other.elements);
  }

  /**
   * Returns true if flowSet is the same type of flow set as this.
   */
  private boolean sameType(Object flowSet) {
    return (flowSet instanceof HashSparseSet);
  }

  @Override
  public HashSparseSet<T> clone() {
    return new HashSparseSet<T>(this);
  }

  @Override
  public FlowSet<T> emptySet() {
    return new HashSparseSet<T>();
  }

  @Override
  public void clear() {
    elements.clear();
    ;
  }

  @Override
  public int size() {
    return elements.size();
  }

  @Override
  public boolean isEmpty() {
    return elements.isEmpty();
  }

  /**
   * Returns a unbacked list of elements in this set.
   */
  @Override
  public List<T> toList() {
    return new ArrayList<T>(elements);
  }

  /*
   * Expand array only when necessary, pointed out by Florian Loitsch March 08, 2002
   */
  @Override
  public void add(T e) {
    elements.add(e);
  }

  @Override
  public void remove(Object obj) {
    elements.remove(obj);
  }

  public void remove(int idx) {
    Iterator<T> itr = elements.iterator();
    int currentIndex = 0;
    Object elem = null;
    while (itr.hasNext()) {
      elem = itr.next();
      if (currentIndex == idx) {
        break;
      }
      currentIndex++;
    }
    if (elem != null) {
      elements.remove(elem);
    }
  }

  @Override
  public void union(FlowSet<T> otherFlow, FlowSet<T> destFlow) {<FILL_FUNCTION_BODY>}

  @Override
  public void intersection(FlowSet<T> otherFlow, FlowSet<T> destFlow) {
    if (sameType(otherFlow) && sameType(destFlow)) {
      HashSparseSet<T> other = (HashSparseSet<T>) otherFlow;
      HashSparseSet<T> dest = (HashSparseSet<T>) destFlow;
      HashSparseSet<T> workingSet = new HashSparseSet<>(this);
      workingSet.elements.retainAll(other.elements);
      dest.elements = workingSet.elements;
    } else {
      super.intersection(otherFlow, destFlow);
    }
  }

  @Override
  public void difference(FlowSet<T> otherFlow, FlowSet<T> destFlow) {
    if (sameType(otherFlow) && sameType(destFlow)) {
      HashSparseSet<T> other = (HashSparseSet<T>) otherFlow;
      HashSparseSet<T> dest = (HashSparseSet<T>) destFlow;
      HashSparseSet<T> workingSet;

      if (dest == other || dest == this) {
        workingSet = new HashSparseSet<T>();
      } else {
        workingSet = dest;
        workingSet.clear();
      }
      for (Object elem : this.elements) {
        if (!other.elements.contains(elem)) {
          workingSet.elements.add((T) elem);
        }
      }
      if (workingSet != dest) {
        workingSet.copy(dest);
      }
    } else {
      super.difference(otherFlow, destFlow);
    }
  }

  @Override
  public boolean contains(Object obj) {
    return elements.contains(obj);
  }

  @Override
  public boolean equals(Object otherFlow) {
    if (sameType(otherFlow)) {
      @SuppressWarnings("unchecked")
      HashSparseSet<T> other = (HashSparseSet<T>) otherFlow;
      return this.elements.equals(other.elements);
    } else {
      return super.equals(otherFlow);
    }
  }

  @Override
  public void copy(FlowSet<T> destFlow) {
    if (sameType(destFlow)) {
      HashSparseSet<T> dest = (HashSparseSet<T>) destFlow;
      dest.elements.clear();
      dest.elements.addAll(this.elements);
    } else {
      super.copy(destFlow);
    }
  }

  @Override
  public Iterator<T> iterator() {
    return elements.iterator();
  }
}

    if (sameType(otherFlow) && sameType(destFlow)) {
      HashSparseSet<T> other = (HashSparseSet<T>) otherFlow;
      HashSparseSet<T> dest = (HashSparseSet<T>) destFlow;
      dest.elements.addAll(this.elements);
      dest.elements.addAll(other.elements);
    } else {
      super.union(otherFlow, destFlow);
    }
  
<methods>public non-sealed void <init>() ,public abstract void add(T) ,public void add(T, FlowSet<T>) ,public void clear() ,public abstract AbstractFlowSet<T> clone() ,public abstract boolean contains(T) ,public void copy(FlowSet<T>) ,public void difference(FlowSet<T>) ,public void difference(FlowSet<T>, FlowSet<T>) ,public FlowSet<T> emptySet() ,public boolean equals(java.lang.Object) ,public int hashCode() ,public void intersection(FlowSet<T>) ,public void intersection(FlowSet<T>, FlowSet<T>) ,public abstract boolean isEmpty() ,public boolean isSubSet(FlowSet<T>) ,public abstract Iterator<T> iterator() ,public abstract void remove(T) ,public void remove(T, FlowSet<T>) ,public abstract int size() ,public abstract List<T> toList() ,public java.lang.String toString() ,public void union(FlowSet<T>) ,public void union(FlowSet<T>, FlowSet<T>) <variables>