Overloading remove: by Index or by Value

Our remove takes a value. It searches for an element and deletes the first match. There is a second operation you might reasonably mean by “remove”: delete the element at a given position. Both are useful. We just overloaded selectionSort to offer two versions under one name, so let’s do the same for remove.

Why we could not do this before

Back when elements were int, these two operations would have had the same signature:

remove(int value)   // remove this value
remove(int index)   // remove the element at this index

Both of them are remove(int). Overloading needs the parameter lists to differ, and here they do not. The parameter names differ, value and index, but Java ignores names when it matches a call to a method. It only reads the types. So these two would not have compiled side by side, and we had to pick one meaning for remove and give up the other.

Now that elements are T, the two signatures differ. “Remove this value” is remove(T value), and “remove at this index” is remove(int index). Those are different parameter types, so both methods can exist in the class at once.

// remove the element at a given index; return what was removed
public T remove(int index) {
  T removed = arr[index];
  for (int j = index; j < size - 1; j++) {
    arr[j] = arr[j + 1];
  }
  size--;
  arr[size] = null;  // null, not 0, now that elements are objects
  return removed;
}

// remove the first element equal to value; return whether anything was removed
public boolean remove(T value) {
  int i = indexOf(value);
  if (i == -1) {
    return false;
  }
  remove(i);  // delegate the shifting to remove(int)
  return true;
}

For a DynamicArray<Student>, the two are never confused:

roster.remove(someStudent);   // remove(T): delete that student
roster.remove(3);             // remove(int): delete the 4th element

A Student argument can only match remove(T), and an int can only match remove(int).

That is because a Student and an int have nothing to do with each other. Suppose the element type were Integer instead. Then the two methods are remove(Integer) and remove(int), and now a call like remove(2) could match either one, since Java converts freely between int and Integer. Both methods still compile, so the compiler does not complain. The question is which one remove(2) resolves to.