Introduction
Finding the sum of each column in a 2D array is another common matrix operation in Java. While it looks similar to calculating row sums, the implementation is slightly different because Java stores a 2D array as an array of rows.
To calculate a column sum, you must keep the column fixed and iterate through every row, collecting the values in that column. This requires swapping the order of the loops compared to the row-sum problem.
In this tutorial, you'll learn multiple approaches to calculate the sum of each column in a 2D array, including nested loops and Java Streams. You'll also learn how to handle jagged arrays, common mistakes to avoid, and best practices.
Problem Statement
Given the following 2D array:
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
The expected column sums are:
Column 0 = 12
Column 1 = 15
Column 2 = 18
Or as an array:
[12, 15, 18]
Why Column Sums Are Different from Row Sums
In Java, a 2D array is actually an array of row arrays.
When calculating row sums, you simply move across one row at a time.
When calculating column sums, you must jump from one row to another while keeping the same column index.
For example, to calculate the first column:
1
4
7
You access:
matrix[0][0]
matrix[1][0]
matrix[2][0]
This is why the loop order is different from the row-sum solution.
Method 1: Using Nested Loops (Recommended)
The simplest and most efficient approach is to swap the loop order.
- The outer loop iterates through columns.
- The inner loop iterates through rows.
Java Program
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[][] matrix = {
{1,2,3},
{4,5,6},
{7,8,9}
};
int numCols = matrix[0].length;
int[] columnSums = new int[numCols];
for (int col = 0; col < numCols; col++) {
int currentColumnSum = 0;
for (int row = 0; row < matrix.length; row++) {
currentColumnSum += matrix[row][col];
}
columnSums[col] = currentColumnSum;
}
System.out.println(Arrays.toString(columnSums));
}
}
Output
[12, 15, 18]
Time Complexity
O(rows × columns)
Space Complexity
O(columns)
Method 2: Using Java Streams
Java Streams provide a concise functional approach.
Java Program
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[][] matrix = {
{1,2,3},
{4,5,6},
{7,8,9}
};
int numCols = matrix[0].length;
int[] columnSums = new int[numCols];
for (int col = 0; col < numCols; col++) {
final int currentCol = col;
columnSums[col] = Arrays.stream(matrix)
.mapToInt(row -> row[currentCol])
.sum();
}
System.out.println(Arrays.toString(columnSums));
}
}
Output
[12, 15, 18]
How It Works
- The outer loop selects one column.
Arrays.stream(matrix)creates a stream of rows.mapToInt()extracts the value from the selected column in every row.sum()calculates the total for that column.
Handling Jagged Arrays
Column sums become slightly more complicated for jagged arrays because rows can have different lengths.
A common solution is to determine the widest row and ignore missing values in shorter rows.
Java Program
import java.util.Arrays;
public class Main {
public static int[] sumColumnsJagged(int[][] matrix) {
int maxColumns = 0;
for (int[] row : matrix) {
maxColumns = Math.max(maxColumns, row.length);
}
int[] columnSums = new int[maxColumns];
for (int[] row : matrix) {
for (int col = 0; col < row.length; col++) {
columnSums[col] += row[col];
}
}
return columnSums;
}
public static void main(String[] args) {
int[][] jagged = {
{1,2},
{3,4,5},
{6}
};
System.out.println(Arrays.toString(sumColumnsJagged(jagged)));
}
}
Output
[10, 6, 5]
Here:
- Column 0 → 1 + 3 + 6 = 10
- Column 1 → 2 + 4 = 6
- Column 2 → 5
Step-by-Step Explanation
Consider the following code:
for (int col = 0; col < numCols; col++) {
int currentColumnSum = 0;
for (int row = 0; row < matrix.length; row++) {
currentColumnSum += matrix[row][col];
}
columnSums[col] = currentColumnSum;
}
Here's what happens:
- Determine the number of columns.
- Select the first column.
- Visit every row while keeping the column fixed.
- Add each value to
currentColumnSum. - Store the result in
columnSums[col]. - Repeat for every remaining column.
Unlike row sums, the outer loop iterates over columns.
Internal Working
For the following matrix:
{
{1,2,3},
{4,5,6},
{7,8,9}
}
The calculation proceeds as follows:
Column 0
1 + 4 + 7 = 12
columnSums[0] = 12
Column 1
2 + 5 + 8 = 15
columnSums[1] = 15
Column 2
3 + 6 + 9 = 18
columnSums[2] = 18
Final Result
[12, 15, 18]
Notice that every column calculation accesses values from different rows.
Real-Life Analogy
Imagine a spreadsheet containing monthly sales data.
Each row represents a different salesperson, while each column represents a month.
To find the total sales for January, you read down the January column, adding one value from every salesperson's row.
You repeat the same process for February, March, and every remaining month.
Best Practices
- Use the swapped loop order (outer loop for columns, inner loop for rows).
- Validate that the matrix is rectangular before using
matrix[0].length. - Use
matrix[0].lengthonly when every row has the same number of columns. - Handle jagged arrays separately if rows can have different lengths.
- If both row sums and column sums are required, compute them together in a single traversal to improve efficiency.
Common Mistakes
Using the Same Loop Order as Row Sums
Incorrect:
for (int row = 0; row < matrix.length; row++)
This calculates row sums instead of column sums.
Correct:
for (int col = 0; col < numCols; col++)
Assuming Every Matrix Is Rectangular
Incorrect:
matrix[row][col]
without checking row length.
This may throw an ArrayIndexOutOfBoundsException for jagged arrays.
Creating the Result Array with the Wrong Size
Incorrect:
int[] columnSums = new int[matrix.length];
Correct:
int[] columnSums = new int[matrix[0].length];
Ignoring Empty Matrices
Before accessing matrix[0], verify that the matrix contains at least one row.
Expert Tips
- Swapping the loop order is a common technique used in many matrix algorithms.
- Column-wise access is generally less cache-friendly than row-wise access because Java stores arrays row by row.
- If you frequently perform column operations, consider transposing the matrix first and then using row-based algorithms.
- If both row sums and column sums are required, compute them together during one traversal instead of scanning the matrix twice.
Comparison of Row Sums and Column Sums
| Feature | Row Sum | Column Sum |
|---|---|---|
| Outer loop | Rows | Columns |
| Inner loop | Columns | Rows |
| Result size | Number of rows | Number of columns |
| Handles jagged arrays | ✅ Naturally | ⚠ Requires special handling |
| Cache efficiency | High | Lower |
Frequently Asked Questions
Why is calculating column sums different from row sums?
Because Java stores data row by row. A column sum requires reading one element from each row instead of traversing a single row.
Does this approach require a rectangular matrix?
Yes. The basic solution assumes that every row contains the same number of columns. Jagged arrays require additional handling.
What is the main difference in the code?
The loop order is swapped.
- Row sums → outer loop over rows.
- Column sums → outer loop over columns.
Can I use Java Streams?
Yes. Streams work well for column sums, although you still need an outer loop to iterate through each column.
Why is column-wise traversal slower?
Because consecutive accesses jump between different row arrays instead of reading contiguous elements within a single row.
How do I handle jagged arrays?
Determine the widest row, create the result array accordingly, and only add values that exist in each row.
Can I calculate row sums and column sums together?
Yes. During a single traversal, update both the current row sum and the corresponding column sum array.
Does matrix transposition help?
Yes. After transposing a matrix, the original columns become rows, allowing you to reuse row-based algorithms for many column operations.