The key is to generalize like mad!

- Force your code to deal with any square puzzle.
- Strive to reuse the same code for rows and columns.

Additional tips:

- Make it object-oriented to reduce parameter-passing clutter.
- Use 0-based indexing for row and column numbers.
- Avoid `ArrayList` — your lists aren't going to grow. Arrays have tidier syntax and better performance.

<!-- -->

    // Use Arrays.binarySearch() like ArrayList.indexOf()
    import static java.util.Arrays.binarySearch;
    
    public class Puzzle {
        public static enum Axis { ROW, COL };
    
        private int[] state;
        private int side;
    
        public Puzzle(int[] state) {
            this.state = state;
            this.side = (int)Math.sqrt(state.length);
            if (side * side != state.length) {
                throw new IllegalArgumentException("Puzzle must be square");
            }
        }
    
        /**
         * @param rc row or col number (0-based)
         */
        private int[] tuple(Axis dir, int rc) {
            int[] result = new int[this.side];
            switch (dir) {
              case ROW:
                System.arraycopy(this.state, rc * this.side, result, 0, this.side);
                break;
              case COL:
                for (int i = 0, j = rc; i < this.side; i++, j += this.side) {
                    result[i] = this.state[j];
                }
                break;
            }
            return result;
        }
    
        private int[] idealTuple(Axis dir, int rc) {
            int[] result = new int[this.side];
            switch (dir) {
              case ROW:
                for (int i = 0, j = rc * this.side + 1; i < this.side; i++, j++) {
                    result[i] = (j < this.state.length) ? j : 0;
                }
                break;
              case COL:
                for (int i = 0, j = this.side + rc + 1; i < this.side; i++, j += this.side) {
                    result[i] = (j < this.state.length) ? j : 0;
                }
                break;
            }
            return result;
        }
    
        public int inversions(Axis dir, int rc) {
            int[] have = this.tuple(dir, rc);
            int[] want = this.idealTuple(dir, rc);
            int inversions = 0;
    
            // For each pair of squares, if both numbers are supposed to be in this
            // tuple, and neither is 0 (blank)...
            for (int i = 1, iPos; i < this.side; i++) {
                if (have[i] != 0 && 0 <= (iPos = binarySearch(want, have[i]))) {
                    for (int j = 0, jPos; j < i; j++) {
                        if (have[j] != 0 && 0 <= (jPos = binarySearch(want, have[j]))) {
                            // ... and are inverted, count it as a conflict.
                            if ((have[i] < have[j]) != (i < j)) {
                                inversions++;
                            }
                        }
                    }
                }
            }
            return inversions;
        }
    
        public static void main(String[] args) {
            Puzzle p = new Puzzle(new int[] {
                3, 2, 1,
                4, 7, 5,
                8, 6, 0
            });
            System.out.printf("Row %d inversions = %d\n", 0, p.inversions(Axis.ROW, 0));
            System.out.printf("Row %d inversions = %d\n", 1, p.inversions(Axis.ROW, 1));
            System.out.printf("Row %d inversions = %d\n", 2, p.inversions(Axis.ROW, 2));
            System.out.printf("Col %d inversions = %d\n", 0, p.inversions(Axis.COL, 0));
            System.out.printf("Col %d inversions = %d\n", 1, p.inversions(Axis.COL, 1));
            System.out.printf("Col %d inversions = %d\n", 2, p.inversions(Axis.COL, 2));
        }
    }