public void copy(FlowSet destFlow) {
    if (sameType(destFlow)) {
      ArraySparseSet dest = (ArraySparseSet) destFlow;

      while (dest.maxElements < this.maxElements) dest.doubleCapacity();

      dest.numElements = this.numElements;

      System.arraycopy(this.elements, 0, dest.elements, 0, this.numElements);
    } else super.copy(destFlow);
  }
  public void union(FlowSet otherFlow, FlowSet destFlow) {
    if (sameType(otherFlow) && sameType(destFlow)) {
      ArraySparseSet other = (ArraySparseSet) otherFlow;
      ArraySparseSet dest = (ArraySparseSet) destFlow;

      // For the special case that dest == other
      if (dest == other) {
        for (int i = 0; i < this.numElements; i++) dest.add(this.elements[i]);
      }

      // Else, force that dest starts with contents of this
      else {
        if (this != dest) copy(dest);

        for (int i = 0; i < other.numElements; i++) dest.add(other.elements[i]);
      }
    } else super.union(otherFlow, destFlow);
  }
  public void difference(FlowSet otherFlow, FlowSet destFlow) {
    if (sameType(otherFlow) && sameType(destFlow)) {
      ArraySparseSet other = (ArraySparseSet) otherFlow;
      ArraySparseSet dest = (ArraySparseSet) destFlow;
      ArraySparseSet workingSet;

      if (dest == other || dest == this) workingSet = new ArraySparseSet();
      else {
        workingSet = dest;
        workingSet.clear();
      }

      for (int i = 0; i < this.numElements; i++) {
        if (!other.contains(this.elements[i])) workingSet.add(this.elements[i]);
      }

      if (workingSet != dest) workingSet.copy(dest);
    } else super.difference(otherFlow, destFlow);
  }