The logic of the algorithm is that it takes all of the non full lines and add them to an array. It leaves the full lines in the old array because the old array will be overwritten. Now, in line 25 it says add incomplete lines to the beginning of the list. This line of code doesn't make sense to me. It says add incomplete lines but it add new, empty lines. Shouldn't it add to the beginning of the array the incomplete lines we took earlier from the initial array and, after these lines, add new lines until the height is reached? So, instead of line 26 i believe it should be like this:
for (int i = lines.size() ; i < height; i++){
  lines.add(new int[width]);
}
public void removeFullLines() {
        // For example, like this:
        // Create a list to store the lines
        // Copy all the non-empty lines into a list.
        // Add incomplete lines to the beginning of the list.
        // Convert the list back into a matrix

        // Create a list to store the lines
        ArrayList<int[]> lines = new ArrayList<>();

        // Copy all the non-empty lines into a list.
        for (int i = 0; i < height; i++) {
            // Count the number of occupied cells in the line - simply sum up all its values
            int count = 0;
            for (int j = 0; j < width; j++) {
                count += matrix[i][j];
            }

            // If the line's sum is not equal to its width, then add it to the list
            if (count != width)
                lines.add(matrix[i]);
        }

        // Add incomplete lines to the beginning of the list.
        while (lines.size() < height) {
            lines.add(0, new int[width]);
        }

        // Convert the list back into a matrix
        matrix = lines.toArray(new int[height][width]);
    }