A Shared indexOf
Both contains and remove start the same way. Each one iterates over the array looking for a value. Writing that search twice means two places to get it right, and two places to change if we ever change how the search works.
This is a kind of decomposition: we extract a shared procedure (duplicate code) into a reusable method, and replace the original code block with a call to this new method.
There is one thing to decide first: what should the extracted method return? contains needs a boolean, but remove needs to know where the value is, so it knows where to start shifting. An index is enough for both, since contains can check the index instead of the value. So the extracted method returns an index. We call it indexOf, and it returns -1 when the value is not there, because -1 is not a valid index and so it cannot be confused with a real answer.
Here it is. The body is the loop copied from contains:
public int indexOf(int value) {
for (int i = 0; i < size; i++) {
if (arr[i] == value) {
return i; // found at index i
}
}
return -1; // not found
}
contains only needs to know whether the value is present, so it checks for -1:
public boolean contains(int value) {
return indexOf(value) != -1;
}
And remove needs the index anyway, to know where to start shifting:
public boolean remove(int value) {
int i = indexOf(value);
if (i == -1) {
return false; // nothing to remove
}
for (int j = i; j < size - 1; j++) {
arr[j] = arr[j + 1]; // shift the rest one slot left
}
size--;
arr[size] = 0;
return true;
}
The search is now in exactly one place. contains and remove each use the result, and neither one has the search code in it. If we later replace the linear scan with something faster, we change indexOf and both callers get the improvement.