There are still two points to comment on. One relates to the header variable and the other relates to the possible need to reassign head.
The previous variable must always holds a reference to the node preceding the node that would be removed by a subsequent legitimate call to remove. So how should previous be initialised before any calls have been made? It is convenient, for simplicity of coding, to introduce a dummy node whose next field is the head of the list. This is done by the declaration
private ListNode header = new ListNode(null, head);The data field is unimportant so, for definiteness, we initialise it to be the null object. Assuming the original list is
head = header.next;The header node is fixed throughout the iteration and its next field will always hold a reference to the first element of the list, whatever removals take place. In fact this reassignment only makes a difference if previous points to the header node, otherwise there is no way of changing header.next. It would in fact be equivalent to replace the above line of code with the conditional statement
if (previous == header) {
head = current;
}
but the unconditional statement is simpler and possibly more
efficient.
As a final comment, we observe that many implementations of linked lists use the dummy header node as a permanent feature, in order to deal with situations like this. For present purposes, it is simpler to introduce it locally as needed.