Skip to main content
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 4/
  5. Java Programming (4343203)/

20 mins· ·
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Lecture 08 - Arrays: 2D Arrays and Advanced Operations

Java Programming

Lecture 08: Arrays - 2D Arrays and Advanced Operations

Course: 4343203 - Java Programming

GTU Semester 4 | Unit 2


Learning Objectives:

  • Master multidimensional array concepts and syntax
  • Implement matrix operations and algorithms
  • Understand jagged arrays and irregular structures
  • Apply advanced array manipulation techniques
  • Work with arrays of objects and complex data

Introduction to Multidimensional Arrays

2D Array (Matrix) is an array of arrays that stores data in a grid format with rows and columns, accessed using two indices.

2D Array Characteristics:

  • Two Dimensions: Rows and columns
  • Matrix Structure: Rectangular grid layout
  • Double Indexing: array[row][col]
  • Homogeneous Data: Same data type throughout
  • Memory Layout: Row-major order in Java

Common Applications:

  • Mathematical matrices and linear algebra
  • Image processing and pixel data
  • Game boards (chess, tic-tac-toe)
  • Spreadsheet and table data
  • Graph adjacency matrices

2D Array Visualization:

int[][] matrix = new int[3][4];
Col→0123
Row 0[0][0][0][1][0][2][0][3]
Row 1[1][0][1][1][1][2][1][3]
Row 2[2][0][2][1][2][2][2][3]
3 rows × 4 columns = 12 elements

2D Array Declaration and Initialization

Declaration Methods:


// Method 1: Step-by-step declaration
int[][] matrix;                    // Declaration
matrix = new int[3][4];           // Memory allocation

// Method 2: Combined declaration and allocation
int[][] matrix = new int[3][4];   // 3 rows, 4 columns

// Method 3: Different syntax variations
int matrix[][] = new int[3][4];   // C-style (valid but not preferred)
int[] matrix[] = new int[3][4];   // Mixed style

// Method 4: Declaration with initial values
int[][] matrix = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

Initialization Examples:


// Initialize with default values (0 for int)
int[][] scores = new int[5][3];

// Initialize with specific values
double[][] prices = {
    {10.99, 15.50, 8.75},
    {12.25, 18.00, 9.50},
    {14.75, 20.25, 11.00}
};

// Character matrix for tic-tac-toe
char[][] board = {
    {' ', ' ', ' '},
    {' ', ' ', ' '},
    {' ', ' ', ' '}
};

// String matrix for student data
String[][] students = {
    {"John", "Math", "85"},
    {"Alice", "Physics", "92"},
    {"Bob", "Chemistry", "78"}
};

// Boolean matrix for adjacency
boolean[][] connections = new boolean[4][4];

Manual Initialization:


public class MatrixInitialization {
    public static void main(String[] args) {
        // Create 3x3 matrix
        int[][] matrix = new int[3][3];
        
        // Initialize with values
        int value = 1;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                matrix[i][j] = value++;
            }
        }
        
        // Display the matrix
        System.out.println("Matrix:");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

Accessing and Manipulating 2D Arrays

Element Access:


int[][] matrix = {
    {10, 20, 30},
    {40, 50, 60},
    {70, 80, 90}
};

// Reading elements
int element = matrix[1][2];  // Gets 60 (row 1, col 2)
int firstElement = matrix[0][0];  // Gets 10
int lastElement = matrix[2][2];   // Gets 90

// Modifying elements
matrix[0][1] = 25;  // Changes 20 to 25
matrix[2][0] = 75;  // Changes 70 to 75

// Using variables as indices
int row = 1, col = 1;
int value = matrix[row][col];  // Gets 50

// Get matrix dimensions
int rows = matrix.length;          // Number of rows (3)
int cols = matrix[0].length;       // Number of columns (3)

Boundary Checking:


public static boolean isValidIndex(int[][] matrix, int row, int col) {
    return matrix != null && 
           row >= 0 && row < matrix.length &&
           col >= 0 && col < matrix[row].length;
}

public static int safeGet(int[][] matrix, int row, int col) {
    if (isValidIndex(matrix, row, col)) {
        return matrix[row][col];
    } else {
        throw new IndexOutOfBoundsException(
            "Invalid indices: [" + row + "][" + col + "]"
        );
    }
}

Matrix Traversal Methods:

1. Nested for loops:


// Row-major traversal
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

// Column-major traversal
for (int j = 0; j < matrix[0].length; j++) {
    for (int i = 0; i < matrix.length; i++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

2. Enhanced for loops:


// Read-only traversal
for (int[] row : matrix) {
    for (int element : row) {
        System.out.print(element + " ");
    }
    System.out.println();
}

3. While loop traversal:


int i = 0;
while (i < matrix.length) {
    int j = 0;
    while (j < matrix[i].length) {
        System.out.print(matrix[i][j] + " ");
        j++;
    }
    System.out.println();
    i++;
}

Matrix Operations

Matrix Addition:


public static int[][] addMatrices(int[][] a, int[][] b) {
    // Check if matrices have same dimensions
    if (a.length != b.length || a[0].length != b[0].length) {
        throw new IllegalArgumentException("Matrices must have same dimensions");
    }
    
    int rows = a.length;
    int cols = a[0].length;
    int[][] result = new int[rows][cols];
    
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            result[i][j] = a[i][j] + b[i][j];
        }
    }
    
    return result;
}

// Example usage
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{5, 6}, {7, 8}};
int[][] sum = addMatrices(matrix1, matrix2);
// Result: {{6, 8}, {10, 12}}

Matrix Subtraction:


public static int[][] subtractMatrices(int[][] a, int[][] b) {
    if (a.length != b.length || a[0].length != b[0].length) {
        throw new IllegalArgumentException("Matrices must have same dimensions");
    }
    
    int rows = a.length;
    int cols = a[0].length;
    int[][] result = new int[rows][cols];
    
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            result[i][j] = a[i][j] - b[i][j];
        }
    }
    
    return result;
}

Matrix Multiplication:


public static int[][] multiplyMatrices(int[][] a, int[][] b) {
    // Check if multiplication is possible
    if (a[0].length != b.length) {
        throw new IllegalArgumentException(
            "Number of columns in first matrix must equal number of rows in second"
        );
    }
    
    int rowsA = a.length;
    int colsA = a[0].length;
    int colsB = b[0].length;
    
    int[][] result = new int[rowsA][colsB];
    
    for (int i = 0; i < rowsA; i++) {
        for (int j = 0; j < colsB; j++) {
            for (int k = 0; k < colsA; k++) {
                result[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    
    return result;
}

// Example: 2x3 * 3x2 = 2x2
int[][] a = {{1, 2, 3}, {4, 5, 6}};
int[][] b = {{7, 8}, {9, 10}, {11, 12}};
int[][] product = multiplyMatrices(a, b);
// Result: {{58, 64}, {139, 154}}

Matrix Transpose:


public static int[][] transposeMatrix(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    
    int[][] transposed = new int[cols][rows];
    
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            transposed[j][i] = matrix[i][j];
        }
    }
    
    return transposed;
}

// In-place transpose for square matrices
public static void transposeSquareMatrix(int[][] matrix) {
    int n = matrix.length;
    
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            // Swap matrix[i][j] and matrix[j][i]
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
}

Jagged Arrays (Irregular Arrays)

Jagged Array Concept:

A jagged array is an array of arrays where each sub-array can have different lengths, creating irregular or "jagged" structure.

Declaration and Initialization:


// Declare jagged array
int[][] jaggedArray = new int[3][];

// Initialize each row with different lengths
jaggedArray[0] = new int[4];  // Row 0: 4 elements
jaggedArray[1] = new int[2];  // Row 1: 2 elements
jaggedArray[2] = new int[5];  // Row 2: 5 elements

// Or initialize with values
int[][] scores = {
    {85, 90, 78, 92},           // Student 1: 4 subjects
    {88, 91},                   // Student 2: 2 subjects
    {75, 82, 89, 95, 87}        // Student 3: 5 subjects
};

Jagged Array Visualization:

Row 0:85907892
Row 1:8891
Row 2:75828995
87

Jagged Array Operations:


public class JaggedArrayDemo {
    public static void main(String[] args) {
        // Create jagged array for student scores
        int[][] studentScores = {
            {85, 90, 78, 92},
            {88, 91},
            {75, 82, 89, 95, 87}
        };
        
        // Display jagged array
        System.out.println("Student Scores:");
        for (int i = 0; i < studentScores.length; i++) {
            System.out.print("Student " + (i + 1) + ": ");
            for (int j = 0; j < studentScores[i].length; j++) {
                System.out.print(studentScores[i][j] + " ");
            }
            System.out.println();
        }
        
        // Calculate average for each student
        System.out.println("\nStudent Averages:");
        for (int i = 0; i < studentScores.length; i++) {
            double average = calculateAverage(studentScores[i]);
            System.out.printf("Student %d: %.2f%n", (i + 1), average);
        }
    }
    
    public static double calculateAverage(int[] scores) {
        if (scores.length == 0) return 0.0;
        
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        return (double) sum / scores.length;
    }
}

Use Cases for Jagged Arrays:

  • Student records with varying number of subjects
  • Employee data with different number of projects
  • Calendar applications (months with different days)
  • Text processing (lines with different word counts)
  • Memory-efficient storage for sparse data

Arrays of Objects

Student Class Example:


class Student {
    private String name;
    private int age;
    private double[] grades;
    
    public Student(String name, int age, double[] grades) {
        this.name = name;
        this.age = age;
        this.grades = grades.clone(); // Defensive copy
    }
    
    public String getName() { return name; }
    public int getAge() { return age; }
    public double[] getGrades() { return grades.clone(); }
    
    public double getAverageGrade() {
        if (grades.length == 0) return 0.0;
        
        double sum = 0;
        for (double grade : grades) {
            sum += grade;
        }
        return sum / grades.length;
    }
    
    @Override
    public String toString() {
        return String.format("Student{name='%s', age=%d, avg=%.2f}", 
                            name, age, getAverageGrade());
    }
}

Working with Student Array:


public class StudentArrayDemo {
    public static void main(String[] args) {
        // Create array of Student objects
        Student[] students = new Student[3];
        
        // Initialize students
        students[0] = new Student("Alice", 20, new double[]{85.5, 90.0, 78.5});
        students[1] = new Student("Bob", 21, new double[]{88.0, 92.5, 87.0});
        students[2] = new Student("Charlie", 19, new double[]{90.5, 85.0, 95.5});
        
        // Display all students
        System.out.println("All Students:");
        for (Student student : students) {
            System.out.println(student);
        }
        
        // Find student with highest average
        Student topStudent = findTopStudent(students);
        System.out.println("\nTop Student: " + topStudent);
        
        // Sort students by average grade
        sortStudentsByAverage(students);
        System.out.println("\nStudents sorted by average:");
        for (Student student : students) {
            System.out.println(student);
        }
    }
    
    public static Student findTopStudent(Student[] students) {
        if (students.length == 0) return null;
        
        Student topStudent = students[0];
        for (int i = 1; i < students.length; i++) {
            if (students[i].getAverageGrade() > topStudent.getAverageGrade()) {
                topStudent = students[i];
            }
        }
        return topStudent;
    }
    
    public static void sortStudentsByAverage(Student[] students) {
        // Simple bubble sort by average grade
        for (int i = 0; i < students.length - 1; i++) {
            for (int j = 0; j < students.length - i - 1; j++) {
                if (students[j].getAverageGrade() < students[j + 1].getAverageGrade()) {
                    // Swap students
                    Student temp = students[j];
                    students[j] = students[j + 1];
                    students[j + 1] = temp;
                }
            }
        }
    }
}

Advanced Array Algorithms

Spiral Matrix Traversal:


public static void spiralTraversal(int[][] matrix) {
    if (matrix == null || matrix.length == 0) return;
    
    int top = 0, bottom = matrix.length - 1;
    int left = 0, right = matrix[0].length - 1;
    
    while (top <= bottom && left <= right) {
        // Traverse top row
        for (int j = left; j <= right; j++) {
            System.out.print(matrix[top][j] + " ");
        }
        top++;
        
        // Traverse right column
        for (int i = top; i <= bottom; i++) {
            System.out.print(matrix[i][right] + " ");
        }
        right--;
        
        // Traverse bottom row (if exists)
        if (top <= bottom) {
            for (int j = right; j >= left; j--) {
                System.out.print(matrix[bottom][j] + " ");
            }
            bottom--;
        }
        
        // Traverse left column (if exists)
        if (left <= right) {
            for (int i = bottom; i >= top; i--) {
                System.out.print(matrix[i][left] + " ");
            }
            left++;
        }
    }
}

Matrix Rotation (90° clockwise):


public static void rotateMatrix90(int[][] matrix) {
    int n = matrix.length;
    
    // Step 1: Transpose the matrix
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
    
    // Step 2: Reverse each row
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n / 2; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[i][n - 1 - j];
            matrix[i][n - 1 - j] = temp;
        }
    }
}

// Alternative: Create new rotated matrix
public static int[][] createRotated90(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[0].length;
    int[][] rotated = new int[cols][rows];
    
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            rotated[j][rows - 1 - i] = matrix[i][j];
        }
    }
    
    return rotated;
}

Matrix Search (in sorted matrix):


// Search in row-wise and column-wise sorted matrix
public static boolean searchMatrix(int[][] matrix, int target) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
        return false;
    }
    
    int row = 0;
    int col = matrix[0].length - 1;  // Start from top-right corner
    
    while (row < matrix.length && col >= 0) {
        if (matrix[row][col] == target) {
            return true;
        } else if (matrix[row][col] > target) {
            col--;  // Move left
        } else {
            row++;  // Move down
        }
    }
    
    return false;
}

// Binary search in each row (for fully sorted matrix)
public static boolean searchSortedMatrix(int[][] matrix, int target) {
    for (int[] row : matrix) {
        if (binarySearch(row, target)) {
            return true;
        }
    }
    return false;
}

public static boolean binarySearch(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        
        if (arr[mid] == target) {
            return true;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    
    return false;
}

Previous Year Exam Questions

Q1. (GTU Summer 2022) Write a Java program to add two matrices and display the result. Handle the case where matrices have different dimensions.

Solution:

import java.util.Scanner;

public class MatrixAddition {
    
    public static int[][] addMatrices(int[][] a, int[][] b) {
        // Check if matrices can be added
        if (a.length != b.length) {
            throw new IllegalArgumentException("Different number of rows: " + a.length + " vs " + b.length);
        }
        
        for (int i = 0; i < a.length; i++) {
            if (a[i].length != b[i].length) {
                throw new IllegalArgumentException("Different number of columns in row " + i);
            }
        }
        
        // Perform addition
        int rows = a.length;
        int cols = a[0].length;
        int[][] result = new int[rows][cols];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result[i][j] = a[i][j] + b[i][j];
            }
        }
        
        return result;
    }
    
    public static void displayMatrix(int[][] matrix, String title) {
        System.out.println(title + ":");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.printf("%4d ", matrix[i][j]);
            }
            System.out.println();
        }
        System.out.println();
    }
    
    public static int[][] inputMatrix(Scanner scanner, String name) {
        System.out.print("Enter number of rows for " + name + ": ");
        int rows = scanner.nextInt();
        System.out.print("Enter number of columns for " + name + ": ");
        int cols = scanner.nextInt();
        
        int[][] matrix = new int[rows][cols];
        
        System.out.println("Enter elements for " + name + ":");
        for (int i = 0; i < rows; i++) {
            System.out.print("Row " + (i + 1) + ": ");
            for (int j = 0; j < cols; j++) {
                matrix[i][j] = scanner.nextInt();
            }
        }
        
        return matrix;
    }
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        try {
            // Input matrices
            System.out.println("=== Matrix Addition Program ===");
            int[][] matrix1 = inputMatrix(scanner, "Matrix A");
            int[][] matrix2 = inputMatrix(scanner, "Matrix B");
            
            // Display input matrices
            displayMatrix(matrix1, "Matrix A");
            displayMatrix(matrix2, "Matrix B");
            
            // Add matrices
            int[][] sum = addMatrices(matrix1, matrix2);
            
            // Display result
            displayMatrix(sum, "Sum (A + B)");
            
            System.out.println("Matrix addition completed successfully!");
            
        } catch (IllegalArgumentException e) {
            System.out.println("Error: Cannot add matrices - " + e.getMessage());
            System.out.println("Matrices must have the same dimensions for addition.");
        } catch (Exception e) {
            System.out.println("An error occurred: " + e.getMessage());
        } finally {
            scanner.close();
        }
        
        // Demo with predefined matrices
        System.out.println("\n=== Demo with predefined matrices ===");
        
        int[][] demoMatrix1 = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        int[][] demoMatrix2 = {
            {9, 8, 7},
            {6, 5, 4},
            {3, 2, 1}
        };
        
        displayMatrix(demoMatrix1, "Demo Matrix A");
        displayMatrix(demoMatrix2, "Demo Matrix B");
        
        try {
            int[][] demoSum = addMatrices(demoMatrix1, demoMatrix2);
            displayMatrix(demoSum, "Demo Sum");
        } catch (Exception e) {
            System.out.println("Demo error: " + e.getMessage());
        }
    }
}

Q2. (GTU Winter 2021) Explain jagged arrays in Java with examples. Write a program to find the largest element in a jagged array.

Solution:

Jagged Arrays Explanation:

Jagged arrays are arrays of arrays where each sub-array can have different lengths. Unlike regular 2D arrays which form a rectangular matrix, jagged arrays create irregular or "jagged" structures.

Key Features:

  • Variable Length: Each row can have different number of elements
  • Memory Efficient: No wasted space for unused elements
  • Flexible Structure: Suitable for irregular data patterns
  • Dynamic Allocation: Rows can be allocated separately
public class JaggedArrayLargest {
    
    public static int findLargestInJaggedArray(int[][] jaggedArray) {
        if (jaggedArray == null || jaggedArray.length == 0) {
            throw new IllegalArgumentException("Array is empty or null");
        }
        
        int largest = Integer.MIN_VALUE;
        boolean hasElements = false;
        
        for (int i = 0; i < jaggedArray.length; i++) {
            if (jaggedArray[i] != null) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    if (jaggedArray[i][j] > largest) {
                        largest = jaggedArray[i][j];
                    }
                    hasElements = true;
                }
            }
        }
        
        if (!hasElements) {
            throw new IllegalArgumentException("No elements found in jagged array");
        }
        
        return largest;
    }
    
    public static void displayJaggedArray(int[][] jaggedArray) {
        System.out.println("Jagged Array Contents:");
        for (int i = 0; i < jaggedArray.length; i++) {
            System.out.print("Row " + i + ": ");
            if (jaggedArray[i] != null) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    System.out.print(jaggedArray[i][j] + " ");
                }
                System.out.println("(Length: " + jaggedArray[i].length + ")");
            } else {
                System.out.println("null");
            }
        }
        System.out.println();
    }
    
    public static void findLargestInEachRow(int[][] jaggedArray) {
        System.out.println("Largest element in each row:");
        for (int i = 0; i < jaggedArray.length; i++) {
            if (jaggedArray[i] != null && jaggedArray[i].length > 0) {
                int rowMax = jaggedArray[i][0];
                for (int j = 1; j < jaggedArray[i].length; j++) {
                    if (jaggedArray[i][j] > rowMax) {
                        rowMax = jaggedArray[i][j];
                    }
                }
                System.out.println("Row " + i + ": " + rowMax);
            } else {
                System.out.println("Row " + i + ": No elements");
            }
        }
        System.out.println();
    }
    
    public static void main(String[] args) {
        // Example 1: Different row lengths
        System.out.println("=== Example 1: Student Scores ===");
        int[][] studentScores = {
            {85, 90, 78, 92, 88},        // Student 1: 5 subjects
            {91, 87},                    // Student 2: 2 subjects  
            {79, 83, 85, 90},           // Student 3: 4 subjects
            {95, 92, 89, 94, 91, 87}    // Student 4: 6 subjects
        };
        
        displayJaggedArray(studentScores);
        
        try {
            int largest = findLargestInJaggedArray(studentScores);
            System.out.println("Largest element in entire jagged array: " + largest);
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        findLargestInEachRow(studentScores);
        
        // Example 2: Irregular data pattern
        System.out.println("=== Example 2: Irregular Data ===");
        int[][] irregularData = {
            {10, 20, 30, 40, 50, 60},   // 6 elements
            {100},                       // 1 element
            {75, 85, 95},               // 3 elements
            {25, 35}                    // 2 elements
        };
        
        displayJaggedArray(irregularData);
        
        try {
            int largest = findLargestInJaggedArray(irregularData);
            System.out.println("Largest element: " + largest);
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        // Example 3: Manual creation
        System.out.println("=== Example 3: Manual Creation ===");
        int[][] manualJagged = new int[4][];
        
        manualJagged[0] = new int[]{1, 3, 5, 7, 9};
        manualJagged[1] = new int[]{2, 4};
        manualJagged[2] = new int[]{10, 20, 30, 40};
        manualJagged[3] = new int[]{100, 200, 300, 400, 500, 600, 700};
        
        displayJaggedArray(manualJagged);
        
        try {
            int largest = findLargestInJaggedArray(manualJagged);
            System.out.println("Largest element: " + largest);
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        
        findLargestInEachRow(manualJagged);
    }
}

Q3. (GTU Summer 2020) Write a Java program to multiply two matrices. Display appropriate error messages for invalid dimensions.

Solution:

public class MatrixMultiplication {
    
    public static int[][] multiplyMatrices(int[][] a, int[][] b) {
        // Validate input matrices
        if (a == null || b == null) {
            throw new IllegalArgumentException("Matrices cannot be null");
        }
        
        if (a.length == 0 || b.length == 0) {
            throw new IllegalArgumentException("Matrices cannot be empty");
        }
        
        // Check if multiplication is possible
        int rowsA = a.length;
        int colsA = a[0].length;
        int rowsB = b.length;
        int colsB = b[0].length;
        
        if (colsA != rowsB) {
            throw new IllegalArgumentException(
                String.format("Cannot multiply matrices: A is %dx%d, B is %dx%d. " +
                             "Number of columns in A (%d) must equal number of rows in B (%d)",
                             rowsA, colsA, rowsB, colsB, colsA, rowsB)
            );
        }
        
        // Perform matrix multiplication
        int[][] result = new int[rowsA][colsB];
        
        for (int i = 0; i < rowsA; i++) {
            for (int j = 0; j < colsB; j++) {
                int sum = 0;
                for (int k = 0; k < colsA; k++) {
                    sum += a[i][k] * b[k][j];
                }
                result[i][j] = sum;
            }
        }
        
        return result;
    }
    
    public static void displayMatrix(int[][] matrix, String name) {
        System.out.println(name + " (" + matrix.length + "x" + matrix[0].length + "):");
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.printf("%6d ", matrix[i][j]);
            }
            System.out.println();
        }
        System.out.println();
    }
    
    public static void demonstrateMultiplication(int[][] a, int[][] b, String description) {
        System.out.println("=== " + description + " ===");
        
        try {
            displayMatrix(a, "Matrix A");
            displayMatrix(b, "Matrix B");
            
            System.out.println("Checking compatibility...");
            System.out.printf("A: %dx%d, B: %dx%d\n", a.length, a[0].length, b.length, b[0].length);
            
            int[][] result = multiplyMatrices(a, b);
            
            System.out.println("✅ Multiplication successful!");
            displayMatrix(result, "Result (A × B)");
            
            // Show calculation for first element as example
            System.out.println("Example calculation for result[0][0]:");
            int sum = 0;
            System.out.print("result[0][0] = ");
            for (int k = 0; k < a[0].length; k++) {
                if (k > 0) System.out.print(" + ");
                System.out.printf("A[0][%d] × B[%d][0]", k, k);
                sum += a[0][k] * b[k][0];
            }
            System.out.println(" = " + sum);
            
        } catch (Exception e) {
            System.out.println("❌ Error: " + e.getMessage());
        }
        
        System.out.println();
    }
    
    public static void main(String[] args) {
        // Test Case 1: Valid multiplication (2x3) × (3x2)
        int[][] matrix1 = {
            {1, 2, 3},
            {4, 5, 6}
        };
        
        int[][] matrix2 = {
            {7, 8},
            {9, 10},
            {11, 12}
        };
        
        demonstrateMultiplication(matrix1, matrix2, "Test Case 1: Valid Multiplication");
        
        // Test Case 2: Square matrix multiplication (2x2) × (2x2)
        int[][] matrix3 = {
            {1, 2},
            {3, 4}
        };
        
        int[][] matrix4 = {
            {5, 6},
            {7, 8}
        };
        
        demonstrateMultiplication(matrix3, matrix4, "Test Case 2: Square Matrices");
        
        // Test Case 3: Invalid dimensions (2x3) × (2x2)
        int[][] matrix5 = {
            {1, 2, 3},
            {4, 5, 6}
        };
        
        int[][] matrix6 = {
            {7, 8},
            {9, 10}
        };
        
        demonstrateMultiplication(matrix5, matrix6, "Test Case 3: Invalid Dimensions");
        
        // Test Case 4: Vector multiplication (1x3) × (3x1)
        int[][] vector1 = {{1, 2, 3}};
        int[][] vector2 = {{4}, {5}, {6}};
        
        demonstrateMultiplication(vector1, vector2, "Test Case 4: Vector Multiplication");
        
        // Test Case 5: Matrix × Vector (3x2) × (2x1)
        int[][] matrix7 = {
            {1, 2},
            {3, 4},
            {5, 6}
        };
        
        int[][] vector3 = {{7}, {8}};
        
        demonstrateMultiplication(matrix7, vector3, "Test Case 5: Matrix × Vector");
        
        System.out.println("=== Matrix Multiplication Rules ===");
        System.out.println("1. For A × B to be valid:");
        System.out.println("   • Number of columns in A must equal number of rows in B");
        System.out.println("   • If A is m×n and B is n×p, then A×B is m×p");
        System.out.println("2. Matrix multiplication is NOT commutative: A×B ≠ B×A (generally)");
        System.out.println("3. Time complexity: O(m×n×p) for (m×n) × (n×p) matrices");
    }
}

Hands-on Lab Exercises

Exercise 1: Matrix Operations Suite

  1. Create a comprehensive matrix operations program:
    • Matrix addition, subtraction, multiplication
    • Matrix transpose and determinant calculation
    • Identity matrix generation and verification
    • Matrix inverse calculation (for 2x2 matrices)
  2. Include input validation and error handling
  3. Create an interactive menu system

Exercise 2: Advanced Array Algorithms

  1. Implement advanced 2D array algorithms:
    • Spiral matrix traversal (clockwise and counterclockwise)
    • Matrix rotation (90°, 180°, 270°)
    • Diagonal traversal and sum calculations
    • Matrix search in sorted 2D array
  2. Test with various matrix sizes and patterns

Exercise 3: Real-world Applications

  1. Build practical applications using 2D arrays:
    • Student gradebook with grade analytics
    • Tic-tac-toe game with AI opponent
    • Image processing simulator (brightness/contrast)
    • Sales data analyzer with monthly/yearly reports
  2. Include data visualization and reporting features

Lecture Summary

Key Concepts Covered:

  • Multidimensional array fundamentals
  • 2D array declaration and initialization
  • Matrix operations (addition, multiplication, transpose)
  • Jagged arrays and irregular structures
  • Arrays of objects and complex data types
  • Advanced algorithms (spiral traversal, rotation)
  • Memory management and performance optimization

Learning Outcomes Achieved:

  • ✅ Master 2D array syntax and operations
  • ✅ Implement matrix mathematical operations
  • ✅ Work with irregular (jagged) array structures
  • ✅ Manage arrays of complex objects
  • ✅ Apply advanced traversal algorithms
  • ✅ Handle multidimensional array exceptions
  • ✅ Optimize memory usage in array applications

Next Lecture: Introduction to Object-Oriented Programming

Topics: Classes, objects, encapsulation, constructors, methods

Thank You!

Questions & Discussion


Next: Lecture 09 - Introduction to Object-Oriented Programming


Course: 4343203 Java Programming
Unit 2: Arrays and Object-Oriented Programming
GTU Semester 4