Suppose an upper triangular matrix of integers is given. What's the best way of storing this in Java? The naive 2d int array is obviously not efficient. The solution I came up with was moved to the answers section.
-
"Best" in which way? Flexibility? Use one of the existing matrix libraries. Performance? Use a plain 1D array. (If performance is really critical and the matrix is "small", you may even consider creating a (rows*cols) array and leaving the lower left of it empty). In any case, I'd stay away from classes that are not intended to be used as a matrix (like "Tables"), or from nested data structures like lists-in-lists. Also note that for the last bit of performance (even when using an array), the *access pattern* is crucial as well, and whether you use row-major or column-major storage – Marco13 Oct 03 '14 at 23:43
-
You can answer your own question: move your solution to an answer (type it in the "Your Answer" box in this page). – Peter O. Oct 04 '14 at 00:09
-
@PeterO. Thanks. Just moved it to the answer section. – user3639557 Oct 04 '14 at 02:09
4 Answers
If you want to save memory, your solution looks great - it's called a packed storage matrix. Column by column, top down, your array would look like this: 1 2 6 3 7 8 4 1 9 5
I would suggest a simpler calculation of your indices, based on the sum formula (n² + n) / 2
(row and column is zero based).
list_index = (column^2 + column) / 2 + row;
An implementation could look like the following:
public class TriangularMatrix {
private final int[] list;
public TriangularMatrix(int size) {
list = new int[sumFormula(size)];
}
public int set(int row, int column, int value) {
validateArguments(row, column);
int listIndex = getListIndex(row, column);
int oldValue = list[listIndex];
list[listIndex] = value;
return oldValue;
}
public int get(int row, int column) {
validateArguments(row, column);
return list[getListIndex(row, column)];
}
private void validateArguments(int row, int column) {
if (row > column) {
throw new IllegalArgumentException("Row (" + row + " given) has to be smaller or equal than column (" + column + " given)!");
}
}
private int getListIndex(int row, int column) {
return sumFormula(column) + row;
}
private int sumFormula(int i) {
return (i*i + i) / 2;
}
}
There is another question on SO discussing the (negative) performance impact, although it's about Fortran.

- 10,054
- 5
- 48
- 85

- 4,309
- 3
- 22
- 31
-
I worked out a solution for the upper triangular matrix case which was what I needed. please have a look and let me know hat you think. – user3639557 Oct 03 '14 at 11:56
-
@user3639557 I changed my answer to match your question - my first version simply wasn't efficient for triangular matrices. – stuXnet Oct 03 '14 at 12:12
If the matrix is always diagonal, I would use:
List<List<Integer>> matrix = ...
If it is an sparse matrix, I would use maps:
Map<Map<Integer>> = ...
In this second case, you may need to wrap the map in a class with get and set operations in order to manage access to new rows and columns.
All this, however depends on your needs, your memory limites and matrix size.

- 27,044
- 8
- 36
- 62
-
I worked out another solution. please have a look and let me know hat you think. – user3639557 Oct 03 '14 at 11:52
-
@user3639557 If yout matrix is always triangular then your solution is right and optimal concerning memory usage. I recommend you to implement its wrapping class with its accesors methods providing a direct access to its elements based on a (i row,j column) index. – Pablo Francisco Pérez Hidalgo Oct 03 '14 at 12:18
I think I found the solution. Here is my solution: Assume you have a 4X4 upper triangular matrix M.
1 2 3 4
0 6 7 1
0 0 8 9
0 0 0 5
If you can map every element of M in a 1d array, that's the best solution. All you need to know is to know which [row,col] of matrix corresponds to which element of your 1d array. Here is how you do the magic:
start_index=((col_index-1)+1)+((col_index-2)+1)+...+1
end_index=start_index + col_index
For example: if I want to find where are the elements on the 3rd column of the matrix, in the array:
start_index=((3-1)+1)+((3-2)+1)+((3-3)+1)=6
end_index=6+3=9
So, all I need to do is to start at index 6 of my array, and read all the elements till index 9 (including 9th element). Following this procedure, then you can store and retrieve all the cells of the nXn matrix in (n + n^2)/2 space.

- 4,791
- 6
- 30
- 55