Skip to content
Java control flow 9 min read

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 long instead of int for factorial — values grow fast. 13! already overflows an int.

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 √n is 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 for null first.


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 int values. 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 StringBuilder in the palindrome check) are often allocated on the stack rather than the heap, skipping garbage collection entirely.
  • Constant folding — expressions like 2 * 10 - 1 that 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

CategoryKey Concepts Practiced
Number programsArithmetic, modulo, loops, Math methods
String programsString / StringBuilder methods, char iteration
Array programsIndexed access, sorting, Arrays utility
Pattern programsNested loops, print formatting
Math programsRecursion, algorithm design

  • 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
Last updated June 13, 2026
Was this helpful?