Print Multiplication Triangle in Java
Problem
Each row of this triangle is a short slice of one number's multiplication table — row i shows i multiplied by 1 through i, using the row index as both the row's identity and its multiplier.
Given a number of rows, print a triangle where row i contains i multiplied by every value from 1 to i.
Java Program
public class MultiplicationTriangle {
public static void main(String[] args) {
int n = 5;
for (int i = 1; i <= n; i++) {
StringBuilder row = new StringBuilder();
for (int j = 1; j <= i; j++) {
if (j > 1) row.append(" ");
row.append(i * j); // row i's own multiplication table, term j
}
System.out.println(row);
}
}
}Output
Core Logic
Multiplying the row number by each position from 1 up to the row number itself fills every row with that row's own multiplication table, growing one term longer each time.
- 1The outer loop runs
ifrom1ton, one row per row number. - 2The inner loop runs
jfrom1toi, one term per column in that row. - 3Each position prints
i * j— rowi's own multiplication table, truncated toiterms. - 4Row
iends upiterms wide, the same growth pattern as Number Triangle.
3*1, 3*2, 3*3, giving 3 6 9.Key Point: Every row uses a different multiplier — row 3's values (3, 6, 9) and row 4's values (4, 8, 12, 16) come from entirely separate multiplication tables, unlike Print Multiplication Table, which always tables the same fixed number.
Why: The total multiplications performed across every row grows proportionally to n², with no storage beyond the loop counters and a per-row StringBuilder.
Key Concepts
Approach 2: Java 8
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class MultiplicationTriangleStream {
public static void main(String[] args) {
int n = 5;
IntStream.rangeClosed(1, n)
.mapToObj(i -> IntStream.rangeClosed(1, i)
.mapToObj(j -> String.valueOf(i * j))
.collect(Collectors.joining(" ")))
.forEach(System.out::println);
}
}
Output
Core Logic
Mapping each column position to that row's own multiple, instead of to the position itself, produces each row's slice of its multiplication table directly.
- 1
IntStream.rangeClosed(1, n)generates one stream element per row. - 2For each row
i, an innerIntStream.rangeClosed(1, i)generates that row's column positions1throughi. - 3
.mapToObj(j -> String.valueOf(i * j))multiplies the row number by each position. - 4
Collectors.joining(" ")joins that row's products beforeforEachprints it.
1, 2, 3 to 3*1, 3*2, 3*3, giving "3 6 9".Key Point: The row index i is captured by the inner lambda from the outer stream — each row's multiplication table depends on knowing which row it's currently building.
Why: The nested streams still compute one product per grid position across all rows, proportional to n², without collecting the full triangle.