Practice Programs
The best way to cement Java concepts is to write code — lots of it. This page collects practical, self-contained programs that reinforce everything from basic arithmetic and loops to string manipulation and pattern printing. Work through them in order, tweak the examples, and try the challenges at the end of each section.
Number Programs
Check Even or Odd
public class EvenOdd {
public static void main(String[] args) {
int number = 17;
if (number % 2 == 0) {
System.out.println(number + " is even.");
} else {
System.out.println(number + " is odd.");
}
}
}
Output:
17 is odd.
Find Factorial
The factorial of n is n * (n-1) * (n-2) * ... * 1. This is a classic for loop exercise.
public class Factorial {
public static void main(String[] args) {
int n = 6;
long factorial = 1;
for (int i = 1; i <= n; i++) {
factorial *= i;
}
System.out.println("Factorial of " + n + " = " + factorial);
}
}
Output:
Factorial of 6 = 720
Tip: Use
longinstead ofintfor factorial — values grow fast.13!already overflows anint.
Check Prime Number
public class PrimeCheck {
public static void main(String[] args) {
int n = 29;
boolean isPrime = n > 1;
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
System.out.println(n + (isPrime ? " is prime." : " is not prime."));
}
}
Output:
29 is prime.
Note: Checking divisors only up to
√nis a well-known optimization — any factor larger than the square root has a corresponding factor smaller than it, so you can stop early.
Fibonacci Series
public class Fibonacci {
public static void main(String[] args) {
int n = 10;
int a = 0, b = 1;
System.out.print("Fibonacci: ");
for (int i = 0; i < n; i++) {
System.out.print(a + " ");
int next = a + b;
a = b;
b = next;
}
}
}
Output:
Fibonacci: 0 1 1 2 3 5 8 13 21 34
Reverse a Number
public class ReverseNumber {
public static void main(String[] args) {
int num = 12345;
int reversed = 0;
while (num != 0) {
reversed = reversed * 10 + (num % 10);
num /= 10;
}
System.out.println("Reversed: " + reversed);
}
}
Output:
Reversed: 54321
Armstrong Number
An Armstrong (narcissistic) number equals the sum of its digits each raised to the power of the number of digits — for example, 153 = 1³ + 5³ + 3³.
public class Armstrong {
public static void main(String[] args) {
int num = 153;
int original = num, sum = 0;
int digits = String.valueOf(num).length();
while (num > 0) {
int d = num % 10;
sum += (int) Math.pow(d, digits);
num /= 10;
}
System.out.println(original + (sum == original ? " is " : " is not ") + "an Armstrong number.");
}
}
Output:
153 is an Armstrong number.
String Programs
Count Vowels in a String
public class CountVowels {
public static void main(String[] args) {
String text = "Hello, Java World!";
int count = 0;
for (char c : text.toLowerCase().toCharArray()) {
if ("aeiou".indexOf(c) != -1) count++;
}
System.out.println("Vowels: " + count);
}
}
Output:
Vowels: 5
Check Palindrome
A palindrome reads the same forwards and backwards — “madam”, “racecar”, etc.
public class Palindrome {
public static void main(String[] args) {
String word = "racecar";
String reversed = new StringBuilder(word).reverse().toString();
System.out.println(word + (word.equals(reversed) ? " is" : " is not") + " a palindrome.");
}
}
Output:
racecar is a palindrome.
Count Word Frequency
import java.util.HashMap;
import java.util.Map;
public class WordFrequency {
public static void main(String[] args) {
String sentence = "the cat sat on the mat the cat";
String[] words = sentence.split(" ");
Map<String, Integer> freq = new HashMap<>();
for (String word : words) {
freq.put(word, freq.getOrDefault(word, 0) + 1);
}
freq.forEach((k, v) -> System.out.println(k + ": " + v));
}
}
Output:
the: 3
cat: 2
sat: 1
on: 1
mat: 1
Tip:
getOrDefault(key, 0)is a clean way to count occurrences without checking fornullfirst.
Array Programs
Find Maximum and Minimum
public class MaxMin {
public static void main(String[] args) {
int[] nums = {3, 17, 8, 42, 5, 1};
int max = nums[0], min = nums[0];
for (int n : nums) {
if (n > max) max = n;
if (n < min) min = n;
}
System.out.println("Max: " + max + ", Min: " + min);
}
}
Output:
Max: 42, Min: 1
Remove Duplicates from an Array
import java.util.Arrays;
import java.util.LinkedHashSet;
public class RemoveDuplicates {
public static void main(String[] args) {
Integer[] nums = {1, 3, 2, 3, 4, 1, 5};
Integer[] unique = new LinkedHashSet<>(Arrays.asList(nums))
.toArray(new Integer[0]);
System.out.println(Arrays.toString(unique));
}
}
Output:
[1, 3, 2, 4, 5]
LinkedHashSet removes duplicates while preserving insertion order — a useful trick to know.
Bubble Sort
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {64, 34, 25, 12, 22, 11, 90};
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
Output:
[11, 12, 22, 25, 34, 64, 90]
Note: Bubble sort has O(n²) time complexity — great for learning, but use
Arrays.sort()in production code.
Pattern Programs
Pattern programs are a favourite in interviews because they test nested loop logic directly. See how loops work for the bytecode perspective.
Right-Angle Triangle of Stars
public class StarTriangle {
public static void main(String[] args) {
int rows = 5;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
Output:
*
* *
* * *
* * * *
* * * * *
Inverted Triangle
public class InvertedTriangle {
public static void main(String[] args) {
int rows = 5;
for (int i = rows; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
System.out.print("* ");
}
System.out.println();
}
}
}
Output:
* * * * *
* * * *
* * *
* *
*
Number Pyramid
public class NumberPyramid {
public static void main(String[] args) {
int rows = 5;
for (int i = 1; i <= rows; i++) {
// print leading spaces
for (int s = rows - i; s > 0; s--) System.out.print(" ");
// print numbers
for (int j = 1; j <= (2 * i - 1); j++) {
System.out.print(j % 2 == 0 ? " " : (j / 2 + 1));
}
System.out.println();
}
}
}
Output:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
Diamond Pattern
public class Diamond {
public static void main(String[] args) {
int n = 5;
// Upper half
for (int i = 1; i <= n; i++) {
for (int s = n - i; s > 0; s--) System.out.print(" ");
for (int j = 0; j < 2 * i - 1; j++) System.out.print("*");
System.out.println();
}
// Lower half
for (int i = n - 1; i >= 1; i--) {
for (int s = n - i; s > 0; s--) System.out.print(" ");
for (int j = 0; j < 2 * i - 1; j++) System.out.print("*");
System.out.println();
}
}
}
Output:
*
***
*****
*******
*********
*******
*****
***
*
Mathematical Programs
GCD (Greatest Common Divisor)
The Euclidean algorithm is one of the oldest and most elegant algorithms in computing.
public class GCD {
static int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
public static void main(String[] args) {
System.out.println("GCD(48, 18) = " + gcd(48, 18));
}
}
Output:
GCD(48, 18) = 6
See the recursion page to understand how this call stack unwinds.
Power Without Math.pow
public class Power {
static long power(int base, int exp) {
long result = 1;
for (int i = 0; i < exp; i++) result *= base;
return result;
}
public static void main(String[] args) {
System.out.println("2^10 = " + power(2, 10));
}
}
Output:
2^10 = 1024
Swap Two Numbers Without a Temp Variable
public class Swap {
public static void main(String[] args) {
int a = 5, b = 9;
a = a + b; // a = 14
b = a - b; // b = 5
a = a - b; // a = 9
System.out.println("a = " + a + ", b = " + b);
}
}
Output:
a = 9, b = 5
Warning: The arithmetic swap can overflow for very large
intvalues. In real code, just use a temp variable — it’s clearer and the JIT compiler optimises it away anyway.
Under the Hood
When you run small programs like these, the JVM does more than just execute your bytecode line by line:
- Loop unrolling — the JIT compiler may unroll short loops (expand iterations inline) to reduce branch overhead.
- Escape analysis — local objects that never leave a method (like the
StringBuilderin the palindrome check) are often allocated on the stack rather than the heap, skipping garbage collection entirely. - Constant folding — expressions like
2 * 10 - 1that can be evaluated at compile time are replaced by the literal value in bytecode. - Stack depth — the recursive GCD with small inputs is typically JIT-inlined. For very deep recursion, use an iterative version to avoid
StackOverflowError.
Understanding these details helps you write code that the JVM can optimise aggressively — but more importantly, it builds the mental model that separates a good Java developer from a great one.
Quick Reference: Program Categories
| Category | Key Concepts Practiced |
|---|---|
| Number programs | Arithmetic, modulo, loops, Math methods |
| String programs | String / StringBuilder methods, char iteration |
| Array programs | Indexed access, sorting, Arrays utility |
| Pattern programs | Nested loops, print formatting |
| Math programs | Recursion, algorithm design |
Related Topics
- for Loop — the workhorse behind most of these programs
- while Loop — used in reverse-number and GCD examples
- Arrays — deeper coverage of array operations used in the array programs
- Recursion — learn the pattern behind the GCD and Fibonacci recursive variants
- How Loops Work (Bytecode & JIT) — understand what the JVM actually does with your loops
- Math Class — reference for
Math.sqrt(),Math.pow(), and more utilities used above