Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRYJava+DRY. Just use the
.length, and provide accessor methods if need be.Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructorUse an instance, not
staticParanoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.I made my
Matriximmutable (seefinal private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be.Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructorUse an instance, not
staticParanoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.I made my
Matriximmutable (seefinal private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be.Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructorUse an instance, not
staticParanoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.I made my
Matriximmutable (seefinal private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
- Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be.Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be. - Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructorUse
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructor - Use an instance, not
staticUse an instance, not
static - Paranoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.Paranoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in. I made my
Matriximmutable (seefinal private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
public final class Matrix { final private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } } - Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be. - Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructor - Use an instance, not
static - Paranoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.
public final class Matrix { private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } } Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the
.length, and provide accessor methods if need be.Use
finalin method args, it will eliminate bugs like you have above, aliasingnumbersincorrectly int the constructorUse an instance, not
staticParanoia is the programmer's lifestyle: I also modified my code to do a
deepCopyof the providedint[][]array, otherwise there is reference leakage, and theMatrixclass would be unable to enforce its own invariants if caller code later modified theint[][]they passed in.I made my
Matriximmutable (seefinal private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
public final class Matrix { final private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } } You need to implement toString() in a meaningful way. For (untested) example:
@Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } This toString() (below) is perhaps suitable for debugging, but will be ugly and confusing if you use it for real user output. An actual solution would probably use a Formatter in some complicated way to produce neatly tabular rows and columns.
public final class Matrix { private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } } You need to implement toString() in a meaningful way. For (untested) example:
@Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } This toString() is perhaps suitable for debugging, but will be ugly and confusing if you use it for real user output. An actual solution would probably use a Formatter in some complicated way to produce neatly tabular rows and columns.
public final class Matrix { private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } } You need to implement toString() in a meaningful way.
This toString() (below) is perhaps suitable for debugging, but will be ugly and confusing if you use it for real user output. An actual solution would probably use a Formatter in some complicated way to produce neatly tabular rows and columns.
public final class Matrix { private int[][] numbers; // note the final, which would find a bug in your cited code above... public Matrix(final int[][] numbers) { // by enforcing these assumptions / invariants here, you don't need to deal // with checking them in other parts of the code. This is long enough that you might // factor it out into a private void sanityCheck() method, which could be // applied elsewhere when there are non-trivial mutations of the internal state if (numbers == null || numbers.length == 0) throw new NullPointerException("Matrix can't have null contents or zero rows"); final int columns = numbers[0].length; if (columns == 0) throw new IllegalArgumentException("Matrix can't have zero columns"); for (int i =1; i < numbers.length; i++) { if (numbers[i] == null) throw new NullPointerException("Matrix can't have null row "+i); if (numbers[i].length != columns) throw new IllegalArgumentException("Matrix can't have differing row lengths!"); } this.numbers = deepCopy(numbers); } public boolean isSquareMatrix() { return rowCount() == columnCount(); } public int rowCount() { return numbers.length; } public int columnCount() {return numbers[0].length; } private static int[][] deepCopy(final int[][] source) { // note we ignore error cases that don't apply because of // invariants in the constructor: assert(source != null); assert(source.length != 0); assert(source[0] != null); assert(source[0].length != 0); int[][] target = new int[source.length][source[0].length]; for (int i = 0; i < source.length; i++) target[i] = Arrays.copyOf(source[i],source[i].length); return target; } public Matrix getTranspose() { int[][] trans = new int[columnCount()][rowCount()]; for (int i = 0; i < rowCount(); i++) for (int j = 0; j < columnCount(); j++) trans[i][j] = getValue(j, i); return new Matrix(trans); } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < numbers.length; i++) { for (int j = 0; j < numbers[i].length; j++) sb.append(' ').append(numbers[i][j]); sb.append('\n'); } return sb.toString(); } public static void main(String[] args) { final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } }; Matrix mat = new Matrix(m1); System.out.print(mat); System.out.print(mat.getTranspose()); } }