Java Programming Data Structures
Collections

Java Arrays - Complete Guide

Master all Java array types with detailed explanations, memory diagrams, and practical examples. Arrays are fundamental data structures for storing multiple values of the same type.

1D Arrays

Linear Data Storage

2D Arrays

Matrix/Tabular Data

Multi-dimensional

Complex Data Structures

1. What are Arrays in Java?

Arrays in Java are objects that store multiple values of the same data type in contiguous memory locations. They provide indexed access to elements and have fixed size once created.

Array Characteristics
  • Fixed Size: Size determined at creation
  • Homogeneous: All elements same type
  • Indexed Access: Elements accessed via index [0 to n-1]
  • Contiguous Memory: Elements stored sequentially
  • Zero-based Indexing: First element at index 0
  • Object Type: Arrays are objects in Java
Types of Arrays
  • 1D Arrays: Single row of elements
  • 2D Arrays: Matrix/table structure
  • Multi-dimensional: Arrays of arrays
  • Jagged Arrays: Variable row lengths
  • Object Arrays: Arrays of objects
  • Primitive Arrays: Arrays of primitives

Quick Reference: Array Types

Different types of arrays available in Java:

1D Arrays 2D Arrays 3D Arrays Jagged Arrays Object Arrays Primitive Arrays String Arrays

2. Array Concepts and Terminology

This table explains key concepts and terminology related to Java arrays:

Concept Description Example Important Notes
Declaration Specifying array type and name int[] numbers; No memory allocated yet
Instantiation Allocating memory for array numbers = new int[5]; Uses new keyword
Initialization Assigning values to elements numbers[0] = 10; Can be done individually or collectively
Length Number of elements in array numbers.length Final field, not a method
Index Position of element in array numbers[2] Range: 0 to length-1
Bounds Valid index range 0 ≤ index < length ArrayIndexOutOfBoundsException if violated
Default Values Initial values for elements int[] → 0, boolean[] → false Depends on data type
Reference Array variable stores reference arr = new int[3]; Not the actual array data
Important Array Facts:
  • Arrays are objects, but they don't extend Object class normally
  • Array length is fixed after creation (cannot be resized)
  • Multi-dimensional arrays are actually "arrays of arrays"
  • All array elements are initialized to default values
  • Arrays implement Cloneable and Serializable interfaces
  • Use java.util.Arrays class for utility methods

3. One-Dimensional (1D) Arrays

1D arrays store elements in a linear sequence. They are the simplest form of arrays with single index access.

Memory Representation of 1D Array
int[] arr
[0]
10
0x1000
[1]
20
0x1004
[2]
30
0x1008
[3]
40
0x100C
[4]
50
0x1010

Contiguous memory allocation for array elements

OneDimensionalArrays.java
public class OneDimensionalArrays {
    public static void main(String[] args) {
        System.out.println("=== 1D ARRAY DECLARATION & INITIALIZATION ===\n");
        
        // Method 1: Declaration, then instantiation, then initialization
        int[] numbers1;
        numbers1 = new int[5];
        numbers1[0] = 10;
        numbers1[1] = 20;
        numbers1[2] = 30;
        numbers1[3] = 40;
        numbers1[4] = 50;
        
        System.out.println("Method 1 - Separate steps:");
        for (int i = 0; i < numbers1.length; i++) {
            System.out.println("numbers1[" + i + "] = " + numbers1[i]);
        }
        
        // Method 2: Declaration, instantiation and initialization in one line
        int[] numbers2 = new int[]{1, 2, 3, 4, 5};
        
        System.out.println("\nMethod 2 - Combined initialization:");
        for (int i = 0; i < numbers2.length; i++) {
            System.out.println("numbers2[" + i + "] = " + numbers2[i]);
        }
        
        // Method 3: Simplified syntax (Java shortcut)
        int[] numbers3 = {100, 200, 300, 400, 500};
        
        System.out.println("\nMethod 3 - Simplified syntax:");
        for (int num : numbers3) { // Enhanced for loop
            System.out.println("Element: " + num);
        }
        
        // Default values for different types
        System.out.println("\n=== DEFAULT VALUES ===");
        
        int[] intArr = new int[3];
        double[] doubleArr = new double[3];
        boolean[] boolArr = new boolean[3];
        String[] strArr = new String[3];
        
        System.out.println("int array default: " + intArr[0]);
        System.out.println("double array default: " + doubleArr[0]);
        System.out.println("boolean array default: " + boolArr[0]);
        System.out.println("String array default: " + strArr[0]);
        
        // Array length property
        System.out.println("\n=== ARRAY LENGTH ===");
        System.out.println("numbers1 length: " + numbers1.length);
        System.out.println("numbers2 length: " + numbers2.length);
        System.out.println("numbers3 length: " + numbers3.length);
        
        // Common array operations
        System.out.println("\n=== COMMON ARRAY OPERATIONS ===");
        
        // Finding sum and average
        int[] scores = {85, 90, 78, 92, 88};
        int sum = 0;
        
        for (int score : scores) {
            sum += score;
        }
        double average = (double) sum / scores.length;
        System.out.println("Sum of scores: " + sum);
        System.out.println("Average score: " + average);
        
        // Finding maximum and minimum
        int max = scores[0];
        int min = scores[0];
        
        for (int i = 1; i < scores.length; i++) {
            if (scores[i] > max) {
                max = scores[i];
            }
            if (scores[i] < min) {
                min = scores[i];
            }
        }
        System.out.println("Maximum score: " + max);
        System.out.println("Minimum score: " + min);
        
        // Searching for an element
        int searchKey = 90;
        boolean found = false;
        int position = -1;
        
        for (int i = 0; i < scores.length; i++) {
            if (scores[i] == searchKey) {
                found = true;
                position = i;
                break;
            }
        }
        System.out.println("\nSearch for " + searchKey + ":");
        System.out.println("Found: " + found);
        System.out.println("Position: " + (found ? position : "Not found"));
        
        // Array copy methods
        System.out.println("\n=== ARRAY COPYING ===");
        
        // Method 1: Using loop
        int[] source = {1, 2, 3, 4, 5};
        int[] destination1 = new int[source.length];
        
        for (int i = 0; i < source.length; i++) {
            destination1[i] = source[i];
        }
        
        // Method 2: Using System.arraycopy()
        int[] destination2 = new int[source.length];
        System.arraycopy(source, 0, destination2, 0, source.length);
        
        // Method 3: Using Arrays.copyOf()
        int[] destination3 = java.util.Arrays.copyOf(source, source.length);
        
        System.out.println("Original: " + java.util.Arrays.toString(source));
        System.out.println("Copy 1: " + java.util.Arrays.toString(destination1));
        System.out.println("Copy 2: " + java.util.Arrays.toString(destination2));
        System.out.println("Copy 3: " + java.util.Arrays.toString(destination3));
        
        // String array example
        System.out.println("\n=== STRING ARRAY EXAMPLE ===");
        String[] fruits = {"Apple", "Banana", "Cherry", "Date", "Elderberry"};
        
        System.out.println("Fruits array:");
        for (String fruit : fruits) {
            System.out.print(fruit + " ");
        }
        System.out.println();
        
        // Array of objects
        System.out.println("\n=== ARRAY OF OBJECTS ===");
        Person[] people = new Person[3];
        people[0] = new Person("John", 25);
        people[1] = new Person("Alice", 30);
        people[2] = new Person("Bob", 28);
        
        for (Person person : people) {
            System.out.println(person);
        }
    }
}

class Person {
    String name;
    int age;
    
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return name + " (" + age + " years)";
    }
}
Important Notes for 1D Arrays:
  • Array indices start at 0 and go up to length-1
  • Accessing index outside bounds throws ArrayIndexOutOfBoundsException
  • length is a field, not a method: use arr.length not arr.length()
  • Arrays are objects, but they're special objects with [] syntax
  • Use enhanced for-loop when you don't need index values
  • Arrays have fixed size - consider ArrayList if you need dynamic sizing

4. Two-Dimensional (2D) Arrays

2D arrays represent matrices or tables with rows and columns. They are essentially "arrays of arrays" in Java.

Memory Representation of 2D Array
int[][] matrix
Row 0 ref
0x2000
1
2
3
Row 1 ref
0x2008
4
5
6
Row 2 ref
0x2010
7
8
9

Each row is a separate 1D array referenced by the main array

TwoDimensionalArrays.java
public class TwoDimensionalArrays {
    public static void main(String[] args) {
        System.out.println("=== 2D ARRAY BASICS ===\n");
        
        // Method 1: Declaration with explicit sizes
        int[][] matrix1 = new int[3][4]; // 3 rows, 4 columns
        
        // Initialize with values
        int value = 1;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                matrix1[i][j] = value++;
            }
        }
        
        System.out.println("3x4 Matrix (Method 1):");
        printMatrix(matrix1);
        
        // Method 2: Declaration with initialization
        int[][] matrix2 = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        System.out.println("\n3x3 Matrix (Method 2):");
        printMatrix(matrix2);
        
        // Method 3: Declaration then initialization
        int[][] matrix3;
        matrix3 = new int[][]{
            {10, 20},
            {30, 40},
            {50, 60}
        };
        
        System.out.println("\n3x2 Matrix (Method 3):");
        printMatrix(matrix3);
        
        // Accessing elements
        System.out.println("\n=== ACCESSING ELEMENTS ===");
        System.out.println("matrix2[0][0] = " + matrix2[0][0]);
        System.out.println("matrix2[1][2] = " + matrix2[1][2]);
        System.out.println("matrix2[2][1] = " + matrix2[2][1]);
        
        // Getting array dimensions
        System.out.println("\n=== ARRAY DIMENSIONS ===");
        System.out.println("matrix1 rows: " + matrix1.length);
        System.out.println("matrix1 columns in row 0: " + matrix1[0].length);
        System.out.println("matrix1 columns in row 1: " + matrix1[1].length);
        
        // Practical example: Student marks
        System.out.println("\n=== STUDENT MARKS EXAMPLE ===");
        int[][] studentMarks = {
            {85, 90, 78},  // Student 1 marks
            {92, 88, 95},  // Student 2 marks
            {76, 85, 80},  // Student 3 marks
            {88, 92, 87}   // Student 4 marks
        };
        
        String[] subjects = {"Math", "Science", "English"};
        String[] students = {"Alice", "Bob", "Charlie", "Diana"};
        
        System.out.println("Student Marks Table:");
        System.out.print("Student\t");
        for (String subject : subjects) {
            System.out.print(subject + "\t");
        }
        System.out.println("Average");
        
        for (int i = 0; i < studentMarks.length; i++) {
            int total = 0;
            System.out.print(students[i] + "\t");
            
            for (int j = 0; j < studentMarks[i].length; j++) {
                System.out.print(studentMarks[i][j] + "\t");
                total += studentMarks[i][j];
            }
            
            double average = (double) total / studentMarks[i].length;
            System.out.printf("%.2f%n", average);
        }
        
        // Matrix operations: Addition
        System.out.println("\n=== MATRIX ADDITION ===");
        int[][] matrixA = {{1, 2}, {3, 4}};
        int[][] matrixB = {{5, 6}, {7, 8}};
        int[][] result = new int[2][2];
        
        System.out.println("Matrix A:");
        printMatrix(matrixA);
        System.out.println("Matrix B:");
        printMatrix(matrixB);
        
        // Add matrices
        for (int i = 0; i < matrixA.length; i++) {
            for (int j = 0; j < matrixA[i].length; j++) {
                result[i][j] = matrixA[i][j] + matrixB[i][j];
            }
        }
        
        System.out.println("Result (A + B):");
        printMatrix(result);
        
        // Transpose of a matrix
        System.out.println("\n=== MATRIX TRANSPOSE ===");
        int[][] original = {{1, 2, 3}, {4, 5, 6}};
        int rows = original.length;
        int cols = original[0].length;
        int[][] transpose = new int[cols][rows];
        
        System.out.println("Original (2x3):");
        printMatrix(original);
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                transpose[j][i] = original[i][j];
            }
        }
        
        System.out.println("Transpose (3x2):");
        printMatrix(transpose);
        
        // Finding maximum in each row
        System.out.println("\n=== FINDING MAX IN EACH ROW ===");
        int[][] data = {
            {34, 56, 12},
            {89, 23, 45},
            {67, 78, 91}
        };
        
        for (int i = 0; i < data.length; i++) {
            int max = data[i][0];
            for (int j = 1; j < data[i].length; j++) {
                if (data[i][j] > max) {
                    max = data[i][j];
                }
            }
            System.out.println("Row " + i + " maximum: " + max);
        }
        
        // String 2D array example
        System.out.println("\n=== STRING 2D ARRAY ===");
        String[][] chessBoard = new String[8][8];
        
        // Initialize chess board
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if ((i + j) % 2 == 0) {
                    chessBoard[i][j] = "White";
                } else {
                    chessBoard[i][j] = "Black";
                }
            }
        }
        
        // Place pieces (simplified)
        chessBoard[0][0] = "White Rook";
        chessBoard[0][7] = "White Rook";
        chessBoard[7][0] = "Black Rook";
        chessBoard[7][7] = "Black Rook";
        
        System.out.println("Chess Board (simplified):");
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                System.out.printf("%-12s", chessBoard[i][j]);
            }
            System.out.println();
        }
    }
    
    // Helper method to print 2D array
    static void printMatrix(int[][] matrix) {
        for (int[] row : matrix) {
            for (int value : row) {
                System.out.print(value + "\t");
            }
            System.out.println();
        }
    }
}
Key Points for 2D Arrays:
  • 2D arrays are actually arrays of 1D arrays
  • arr.length gives number of rows
  • arr[i].length gives number of columns in row i
  • Rows can have different lengths (jagged arrays)
  • Use nested loops to traverse 2D arrays
  • Memory for each row is allocated separately
  • Useful for matrices, tables, grids, and game boards

5. Jagged Arrays (Variable-sized Arrays)

Jagged arrays are 2D arrays where each row can have a different number of columns. They provide memory efficiency when row sizes vary.

Memory Representation of Jagged Array
int[][] jagged
Row 0 ref
0x3000
1
2
Row 1 ref
0x3008
3
4
5
6
Row 2 ref
0x3010
7

Rows have different lengths (2, 4, and 1 elements)

JaggedArrays.java
public class JaggedArrays {
    public static void main(String[] args) {
        System.out.println("=== JAGGED ARRAY BASICS ===\n");
        
        // Method 1: Create jagged array with different row sizes
        int[][] jagged1 = new int[3][]; // 3 rows, columns unspecified
        
        // Initialize each row with different sizes
        jagged1[0] = new int[2];  // Row 0 has 2 columns
        jagged1[1] = new int[4];  // Row 1 has 4 columns
        jagged1[2] = new int[3];  // Row 2 has 3 columns
        
        // Fill with values
        int value = 1;
        for (int i = 0; i < jagged1.length; i++) {
            for (int j = 0; j < jagged1[i].length; j++) {
                jagged1[i][j] = value++;
            }
        }
        
        System.out.println("Jagged Array 1:");
        printJaggedArray(jagged1);
        
        // Method 2: Initialize with values directly
        int[][] jagged2 = {
            {1, 2},           // Row 0: 2 elements
            {3, 4, 5, 6},     // Row 1: 4 elements
            {7, 8, 9},        // Row 2: 3 elements
            {10}              // Row 3: 1 element
        };
        
        System.out.println("\nJagged Array 2 (direct initialization):");
        printJaggedArray(jagged2);
        
        // Practical example: Student test scores (different number of tests)
        System.out.println("\n=== STUDENT TEST SCORES EXAMPLE ===");
        int[][] testScores = new int[4][]; // 4 students
        
        // Each student took different number of tests
        testScores[0] = new int[]{85, 90, 78};     // 3 tests
        testScores[1] = new int[]{92, 88};         // 2 tests
        testScores[2] = new int[]{76, 85, 80, 88}; // 4 tests
        testScores[3] = new int[]{95};             // 1 test
        
        String[] studentNames = {"Alice", "Bob", "Charlie", "Diana"};
        
        System.out.println("Student Test Scores:");
        for (int i = 0; i < testScores.length; i++) {
            System.out.print(studentNames[i] + ": ");
            int sum = 0;
            
            for (int j = 0; j < testScores[i].length; j++) {
                System.out.print(testScores[i][j] + " ");
                sum += testScores[i][j];
            }
            
            double average = (double) sum / testScores[i].length;
            System.out.printf("(Average: %.2f)%n", average);
        }
        
        // Example: Pascal's Triangle using jagged array
        System.out.println("\n=== PASCAL'S TRIANGLE ===");
        int rows = 5;
        int[][] pascal = new int[rows][];
        
        for (int i = 0; i < rows; i++) {
            pascal[i] = new int[i + 1]; // Each row has i+1 elements
            pascal[i][0] = 1; // First element is always 1
            pascal[i][i] = 1; // Last element is always 1
            
            // Fill middle elements
            for (int j = 1; j < i; j++) {
                pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j];
            }
        }
        
        System.out.println("Pascal's Triangle (5 rows):");
        for (int i = 0; i < pascal.length; i++) {
            // Add spacing for pyramid shape
            for (int k = 0; k < rows - i; k++) {
                System.out.print("  ");
            }
            
            for (int j = 0; j < pascal[i].length; j++) {
                System.out.printf("%4d", pascal[i][j]);
            }
            System.out.println();
        }
        
        // Example: Employee skills matrix
        System.out.println("\n=== EMPLOYEE SKILLS MATRIX ===");
        String[][] employeeSkills = new String[3][];
        
        employeeSkills[0] = new String[]{"Java", "Python", "SQL"};
        employeeSkills[1] = new String[]{"JavaScript", "HTML", "CSS", "React"};
        employeeSkills[2] = new String[]{"C++", "Algorithms", "Data Structures"};
        
        String[] employees = {"John (Backend)", "Sarah (Frontend)", "Mike (Systems)"};
        
        System.out.println("Employee Skills:");
        for (int i = 0; i < employeeSkills.length; i++) {
            System.out.print(employees[i] + ": ");
            for (int j = 0; j < employeeSkills[i].length; j++) {
                System.out.print(employeeSkills[i][j]);
                if (j < employeeSkills[i].length - 1) {
                    System.out.print(", ");
                }
            }
            System.out.println();
        }
        
        // Dynamic jagged array example
        System.out.println("\n=== DYNAMIC JAGGED ARRAY ===");
        java.util.Scanner scanner = new java.util.Scanner(System.in);
        
        System.out.print("Enter number of rows: ");
        int numRows = scanner.nextInt();
        int[][] dynamicJagged = new int[numRows][];
        
        for (int i = 0; i < numRows; i++) {
            System.out.print("Enter number of columns for row " + i + ": ");
            int numCols = scanner.nextInt();
            dynamicJagged[i] = new int[numCols];
            
            System.out.println("Enter " + numCols + " values for row " + i + ":");
            for (int j = 0; j < numCols; j++) {
                dynamicJagged[i][j] = scanner.nextInt();
            }
        }
        
        System.out.println("\nDynamic Jagged Array:");
        printJaggedArray(dynamicJagged);
        
        // Memory efficiency demonstration
        System.out.println("\n=== MEMORY EFFICIENCY ===");
        System.out.println("Regular 4x4 array: 16 elements (may waste memory)");
        System.out.println("Jagged array with rows of size 1,4,2,3: 10 elements (saves memory)");
        
        // Convert jagged array to regular array (if needed)
        System.out.println("\n=== CONVERTING TO REGULAR ARRAY ===");
        // Find maximum row length
        int maxLength = 0;
        for (int[] row : jagged2) {
            if (row.length > maxLength) {
                maxLength = row.length;
            }
        }
        
        // Create regular array
        int[][] regular = new int[jagged2.length][maxLength];
        for (int i = 0; i < jagged2.length; i++) {
            System.arraycopy(jagged2[i], 0, regular[i], 0, jagged2[i].length);
            // Remaining columns will have default value 0
        }
        
        System.out.println("Converted to regular " + jagged2.length + "x" + maxLength + " array:");
        printMatrix(regular);
    }
    
    // Helper method to print jagged array
    static void printJaggedArray(int[][] jagged) {
        for (int i = 0; i < jagged.length; i++) {
            System.out.print("Row " + i + " (" + jagged[i].length + " elements): ");
            for (int j = 0; j < jagged[i].length; j++) {
                System.out.print(jagged[i][j] + " ");
            }
            System.out.println();
        }
    }
    
    // Helper method to print regular matrix
    static void printMatrix(int[][] matrix) {
        for (int[] row : matrix) {
            for (int value : row) {
                System.out.print(value + "\t");
            }
            System.out.println();
        }
    }
}
When to Use Jagged Arrays:
  • When rows have significantly different sizes
  • When memory efficiency is important
  • For representing triangular matrices
  • When dealing with irregular data structures
  • For sparse matrices (mostly zero values)
  • When data is naturally variable-length by category

6. Multi-dimensional Arrays

Java supports arrays with more than two dimensions. These are arrays of arrays of arrays, useful for representing 3D+ data structures.

MultiDimensionalArrays.java
public class MultiDimensionalArrays {
    public static void main(String[] args) {
        System.out.println("=== 3D ARRAYS ===\n");
        
        // 3D array declaration and initialization
        int[][][] cube = new int[3][3][3]; // 3x3x3 cube
        
        // Fill the 3D array
        int value = 1;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                for (int k = 0; k < 3; k++) {
                    cube[i][j][k] = value++;
                }
            }
        }
        
        System.out.println("3D Array (Cube 3x3x3):");
        print3DArray(cube);
        
        // Direct initialization of 3D array
        int[][][] colors = {
            { // First 2D array (layer 0)
                {255, 0, 0},    // Red
                {0, 255, 0},    // Green
                {0, 0, 255}     // Blue
            },
            { // Second 2D array (layer 1)
                {255, 255, 0},  // Yellow
                {255, 0, 255},  // Magenta
                {0, 255, 255}   // Cyan
            },
            { // Third 2D array (layer 2)
                {128, 0, 0},    // Dark Red
                {0, 128, 0},    // Dark Green
                {0, 0, 128}     // Dark Blue
            }
        };
        
        System.out.println("\nRGB Color Cube:");
        for (int i = 0; i < colors.length; i++) {
            System.out.println("Layer " + i + ":");
            for (int j = 0; j < colors[i].length; j++) {
                System.out.print("  ");
                for (int k = 0; k < colors[i][j].length; k++) {
                    System.out.print(colors[i][j][k] + " ");
                }
                System.out.println();
            }
        }
        
        // Practical example: School timetable (3D)
        System.out.println("\n=== SCHOOL TIMETABLE (3D) ===");
        String[][][] timetable = new String[5][8][2]; // 5 days, 8 periods, 2 pieces of info
        
        // Initialize with sample data
        timetable[0][0][0] = "Math";          // Monday, Period 1, Subject
        timetable[0][0][1] = "Room 101";      // Monday, Period 1, Room
        
        timetable[0][1][0] = "Science";
        timetable[0][1][1] = "Lab 201";
        
        timetable[1][0][0] = "English";       // Tuesday, Period 1
        timetable[1][0][1] = "Room 102";
        
        // Display timetable for Monday
        System.out.println("Monday Schedule:");
        System.out.println("Period\tSubject\t\tRoom");
        System.out.println("----------------------------");
        for (int period = 0; period < 8; period++) {
            if (timetable[0][period][0] != null) {
                System.out.printf("%d\t%-12s\t%s%n", 
                    period + 1, 
                    timetable[0][period][0], 
                    timetable[0][period][1]);
            }
        }
        
        // 4D Array example: Yearly data
        System.out.println("\n=== 4D ARRAY EXAMPLE ===");
        // 3 years, 4 quarters, 3 months, 2 metrics (revenue, expenses)
        double[][][][] yearlyData = new double[3][4][3][2];
        
        // Fill with sample financial data
        for (int year = 0; year < 3; year++) {
            for (int quarter = 0; quarter < 4; quarter++) {
                for (int month = 0; month < 3; month++) {
                    yearlyData[year][quarter][month][0] = 10000 + (year * 5000) + (quarter * 1000) + (month * 100); // Revenue
                    yearlyData[year][quarter][month][1] = 5000 + (year * 2000) + (quarter * 500) + (month * 50);   // Expenses
                }
            }
        }
        
        // Display summary
        System.out.println("Yearly Financial Data (Sample):");
        System.out.println("Year\tQuarter\tMonth\tRevenue\tExpenses\tProfit");
        System.out.println("---------------------------------------------------");
        
        double totalProfit = 0;
        for (int year = 0; year < yearlyData.length; year++) {
            for (int quarter = 0; quarter < yearlyData[year].length; quarter++) {
                for (int month = 0; month < yearlyData[year][quarter].length; month++) {
                    double revenue = yearlyData[year][quarter][month][0];
                    double expenses = yearlyData[year][quarter][month][1];
                    double profit = revenue - expenses;
                    totalProfit += profit;
                    
                    System.out.printf("%d\t%d\t%d\t%.2f\t%.2f\t\t%.2f%n",
                        year + 2020, quarter + 1, month + 1,
                        revenue, expenses, profit);
                }
            }
        }
        System.out.printf("Total Profit: %.2f%n", totalProfit);
        
        // Jagged 3D array example
        System.out.println("\n=== JAGGED 3D ARRAY ===");
        int[][][] jagged3D = new int[3][][]; // 3 layers
        
        // Layer 0: 2 rows, each with different columns
        jagged3D[0] = new int[2][];
        jagged3D[0][0] = new int[]{1, 2, 3};      // 3 columns
        jagged3D[0][1] = new int[]{4, 5};         // 2 columns
        
        // Layer 1: 3 rows
        jagged3D[1] = new int[3][];
        jagged3D[1][0] = new int[]{6, 7, 8, 9};   // 4 columns
        jagged3D[1][1] = new int[]{10};           // 1 column
        jagged3D[1][2] = new int[]{11, 12};       // 2 columns
        
        // Layer 2: 1 row
        jagged3D[2] = new int[1][];
        jagged3D[2][0] = new int[]{13, 14, 15, 16, 17}; // 5 columns
        
        System.out.println("Jagged 3D Array Structure:");
        for (int i = 0; i < jagged3D.length; i++) {
            System.out.println("Layer " + i + " (" + jagged3D[i].length + " rows):");
            for (int j = 0; j < jagged3D[i].length; j++) {
                System.out.print("  Row " + j + " (" + jagged3D[i][j].length + " cols): ");
                for (int k = 0; k < jagged3D[i][j].length; k++) {
                    System.out.print(jagged3D[i][j][k] + " ");
                }
                System.out.println();
            }
        }
        
        // Performance consideration
        System.out.println("\n=== PERFORMANCE CONSIDERATIONS ===");
        System.out.println("Higher dimensions = More memory + Slower access");
        System.out.println("Consider using classes/objects for complex data");
        System.out.println("Alternative: Use collections (ArrayList, etc.)");
        
        // Real-world analogy: Rubik's cube
        System.out.println("\n=== REAL-WORLD ANALOGY: RUBIK'S CUBE ===");
        char[][][] rubiksCube = new char[3][3][3];
        
        // Initialize faces (simplified)
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                for (int k = 0; k < 3; k++) {
                    if (i == 0) rubiksCube[i][j][k] = 'W'; // White face
                    else if (i == 2) rubiksCube[i][j][k] = 'Y'; // Yellow face
                    else if (j == 0) rubiksCube[i][j][k] = 'B'; // Blue face
                    else if (j == 2) rubiksCube[i][j][k] = 'G'; // Green face
                    else if (k == 0) rubiksCube[i][j][k] = 'R'; // Red face
                    else if (k == 2) rubiksCube[i][j][k] = 'O'; // Orange face
                    else rubiksCube[i][j][k] = 'X'; // Internal
                }
            }
        }
        
        System.out.println("Rubik's Cube Representation (3x3x3):");
        System.out.println("W=White, Y=Yellow, B=Blue, G=Green, R=Red, O=Orange");
    }
    
    // Helper method to print 3D array
    static void print3DArray(int[][][] array) {
        for (int i = 0; i < array.length; i++) {
            System.out.println("Layer " + i + ":");
            for (int j = 0; j < array[i].length; j++) {
                for (int k = 0; k < array[i][j].length; k++) {
                    System.out.printf("%3d ", array[i][j][k]);
                }
                System.out.println();
            }
            System.out.println();
        }
    }
}

7. Arrays Class and Utility Methods

The java.util.Arrays class provides static methods for array manipulation, sorting, searching, and comparison.

ArraysClassExamples.java
import java.util.Arrays;
import java.util.Comparator;

public class ArraysClassExamples {
    public static void main(String[] args) {
        System.out.println("=== java.util.Arrays CLASS METHODS ===\n");
        
        // 1. Arrays.toString() - Convert array to readable string
        int[] numbers = {5, 2, 8, 1, 9};
        System.out.println("1. toString(): " + Arrays.toString(numbers));
        
        // 2. Arrays.sort() - Sort arrays
        int[] unsorted = {5, 2, 8, 1, 9, 3};
        System.out.println("\n2. sort() method:");
        System.out.println("Before sorting: " + Arrays.toString(unsorted));
        
        Arrays.sort(unsorted);
        System.out.println("After sorting: " + Arrays.toString(unsorted));
        
        // Sort only part of array
        int[] partial = {10, 5, 8, 3, 7, 2, 9};
        System.out.println("\nPartial sort (indices 2 to 5):");
        System.out.println("Before: " + Arrays.toString(partial));
        Arrays.sort(partial, 2, 6); // Sort from index 2 to 5 (exclusive)
        System.out.println("After: " + Arrays.toString(partial));
        
        // 3. Arrays.binarySearch() - Search in sorted array
        int[] sorted = {1, 3, 5, 7, 9, 11, 13};
        int key = 7;
        int index = Arrays.binarySearch(sorted, key);
        System.out.println("\n3. binarySearch():");
        System.out.println("Array: " + Arrays.toString(sorted));
        System.out.println("Search for " + key + ": Index = " + index);
        
        // If element not found
        key = 8;
        index = Arrays.binarySearch(sorted, key);
        System.out.println("Search for " + key + ": Index = " + index + " (not found)");
        
        // 4. Arrays.fill() - Fill array with values
        int[] fillArray = new int[5];
        System.out.println("\n4. fill() method:");
        System.out.println("Before fill: " + Arrays.toString(fillArray));
        
        Arrays.fill(fillArray, 42);
        System.out.println("After fill with 42: " + Arrays.toString(fillArray));
        
        // Fill part of array
        int[] partialFill = new int[10];
        Arrays.fill(partialFill, 3, 7, 99); // Fill indices 3 to 6 with 99
        System.out.println("Partial fill (indices 3-6): " + Arrays.toString(partialFill));
        
        // 5. Arrays.copyOf() - Copy arrays
        int[] original = {1, 2, 3, 4, 5};
        int[] copy1 = Arrays.copyOf(original, 3); // Copy first 3 elements
        int[] copy2 = Arrays.copyOf(original, 7); // Copy all + 2 default values
        
        System.out.println("\n5. copyOf() method:");
        System.out.println("Original: " + Arrays.toString(original));
        System.out.println("Copy (length 3): " + Arrays.toString(copy1));
        System.out.println("Copy (length 7): " + Arrays.toString(copy2));
        
        // 6. Arrays.copyOfRange() - Copy range of array
        int[] source = {10, 20, 30, 40, 50, 60};
        int[] rangeCopy = Arrays.copyOfRange(source, 2, 5); // Copy indices 2 to 4
        
        System.out.println("\n6. copyOfRange() method:");
        System.out.println("Source: " + Arrays.toString(source));
        System.out.println("Copy range [2,5): " + Arrays.toString(rangeCopy));
        
        // 7. Arrays.equals() - Compare arrays
        int[] arr1 = {1, 2, 3};
        int[] arr2 = {1, 2, 3};
        int[] arr3 = {1, 2, 4};
        
        System.out.println("\n7. equals() method:");
        System.out.println("arr1 = " + Arrays.toString(arr1));
        System.out.println("arr2 = " + Arrays.toString(arr2));
        System.out.println("arr3 = " + Arrays.toString(arr3));
        System.out.println("arr1.equals(arr2): " + arr1.equals(arr2)); // False - compares references
        System.out.println("Arrays.equals(arr1, arr2): " + Arrays.equals(arr1, arr2)); // True - compares content
        System.out.println("Arrays.equals(arr1, arr3): " + Arrays.equals(arr1, arr3)); // False
        
        // 8. Arrays.deepEquals() - Compare multidimensional arrays
        int[][] deep1 = {{1, 2}, {3, 4}};
        int[][] deep2 = {{1, 2}, {3, 4}};
        int[][] deep3 = {{1, 2}, {3, 5}};
        
        System.out.println("\n8. deepEquals() method:");
        System.out.println("deep1 = " + Arrays.deepToString(deep1));
        System.out.println("deep2 = " + Arrays.deepToString(deep2));
        System.out.println("deep3 = " + Arrays.deepToString(deep3));
        System.out.println("Arrays.equals(deep1, deep2): " + Arrays.equals(deep1, deep2)); // False
        System.out.println("Arrays.deepEquals(deep1, deep2): " + Arrays.deepEquals(deep1, deep2)); // True
        System.out.println("Arrays.deepEquals(deep1, deep3): " + Arrays.deepEquals(deep1, deep3)); // False
        
        // 9. Arrays.deepToString() - Convert multidimensional arrays to string
        int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        System.out.println("\n9. deepToString() method:");
        System.out.println("Matrix: " + Arrays.deepToString(matrix));
        
        // 10. Arrays.stream() - Convert array to stream
        System.out.println("\n10. stream() method:");
        int[] streamArray = {1, 2, 3, 4, 5};
        System.out.println("Array: " + Arrays.toString(streamArray));
        System.out.println("Sum using stream: " + Arrays.stream(streamArray).sum());
        System.out.println("Average using stream: " + Arrays.stream(streamArray).average().orElse(0));
        
        // 11. Arrays.setAll() - Set all elements using generator function
        int[] setAllArray = new int[5];
        Arrays.setAll(setAllArray, i -> i * 2); // Set each element to index * 2
        
        System.out.println("\n11. setAll() method:");
        System.out.println("Array: " + Arrays.toString(setAllArray));
        
        // 12. Arrays.parallelSort() - Parallel sorting for large arrays
        int[] largeArray = new int[10000];
        Arrays.setAll(largeArray, i -> (int)(Math.random() * 10000));
        
        System.out.println("\n12. parallelSort() method:");
        System.out.println("Large array created with 10000 random numbers");
        System.out.println("Using parallelSort for better performance on multi-core systems");
        
        // 13. Sorting with custom comparator (for object arrays)
        System.out.println("\n13. Sorting with Comparator:");
        String[] names = {"John", "Alice", "Bob", "Charlie", "Diana"};
        System.out.println("Before sorting: " + Arrays.toString(names));
        
        // Sort by length
        Arrays.sort(names, Comparator.comparingInt(String::length));
        System.out.println("Sorted by length: " + Arrays.toString(names));
        
        // Sort alphabetically (default)
        Arrays.sort(names);
        System.out.println("Sorted alphabetically: " + Arrays.toString(names));
        
        // 14. Arrays.mismatch() - Find first index where arrays differ
        int[] mismatch1 = {1, 2, 3, 4, 5};
        int[] mismatch2 = {1, 2, 3, 9, 5};
        
        System.out.println("\n14. mismatch() method:");
        System.out.println("Array1: " + Arrays.toString(mismatch1));
        System.out.println("Array2: " + Arrays.toString(mismatch2));
        System.out.println("First mismatch at index: " + Arrays.mismatch(mismatch1, mismatch2));
        
        // 15. Practical example: Processing student grades
        System.out.println("\n=== PRACTICAL EXAMPLE: STUDENT GRADES ===");
        double[] grades = {85.5, 92.0, 78.5, 88.0, 95.5, 82.0};
        
        System.out.println("Original grades: " + Arrays.toString(grades));
        
        // Sort grades
        double[] sortedGrades = Arrays.copyOf(grades, grades.length);
        Arrays.sort(sortedGrades);
        System.out.println("Sorted grades: " + Arrays.toString(sortedGrades));
        
        // Find median
        double median;
        if (sortedGrades.length % 2 == 0) {
            median = (sortedGrades[sortedGrades.length/2 - 1] + sortedGrades[sortedGrades.length/2]) / 2;
        } else {
            median = sortedGrades[sortedGrades.length/2];
        }
        System.out.println("Median grade: " + median);
        
        // Find students above average
        double sum = Arrays.stream(grades).sum();
        double average = sum / grades.length;
        System.out.println("Average grade: " + average);
        
        System.out.println("Grades above average:");
        Arrays.stream(grades)
              .filter(g -> g > average)
              .forEach(g -> System.out.print(g + " "));
        System.out.println();
    }
}
Key Points about Arrays Class:
  • All methods are static - call using Arrays.methodName()
  • Arrays.toString() for 1D arrays, Arrays.deepToString() for multi-dimensional
  • Arrays.equals() compares 1D arrays, Arrays.deepEquals() for multi-dimensional
  • Arrays.sort() uses dual-pivot quicksort for primitives, TimSort for objects
  • Arrays.binarySearch() requires sorted array
  • Use Arrays.parallelSort() for large arrays on multi-core systems
  • Arrays.stream() enables functional programming on arrays

8. Common Mistakes and Best Practices

Common Mistakes with Arrays:
  1. ArrayIndexOutOfBoundsException: Accessing arr[arr.length] or negative index
  2. NullPointerException: Accessing elements of uninitialized array: int[] arr; arr[0] = 5;
  3. Assuming array size can change: Arrays have fixed size after creation
  4. Using == to compare arrays: Compares references, not content
  5. Forgetting to import Arrays class: Arrays.sort() needs import
  6. Confusing length field with method: arr.length not arr.length()
  7. Shallow copy vs deep copy: arr2 = arr1 copies reference, not elements
Best Practices
  • Always validate array indices before access
  • Use enhanced for-loop when index not needed
  • Consider ArrayList for dynamic sizing needs
  • Use Arrays.toString() for debugging
  • Initialize arrays with meaningful default values
  • Use System.arraycopy() for efficient copying
  • Consider memory usage with large multi-dimensional arrays
Performance Tips
  • Prefer 1D arrays over multi-dimensional when possible
  • Use Arrays.sort() for sorting large arrays
  • Cache array length in loop variables: for (int i=0, n=arr.length; i
  • Use primitive arrays for performance-critical code
  • Consider memory locality for cache efficiency
  • Use Arrays.parallelSort() for very large arrays
  • Reuse arrays instead of creating new ones in loops
ArrayBestPractices.java
import java.util.Arrays;

public class ArrayBestPractices {
    public static void main(String[] args) {
        System.out.println("=== ARRAY BEST PRACTICES ===\n");
        
        // 1. Safe array access
        int[] arr = {1, 2, 3, 4, 5};
        int index = 10;
        
        // BAD: arr[index] = 100; // Throws ArrayIndexOutOfBoundsException
        // GOOD:
        if (index >= 0 && index < arr.length) {
            arr[index] = 100;
        } else {
            System.out.println("Invalid index: " + index);
        }
        
        // 2. Proper array copying
        int[] original = {1, 2, 3, 4, 5};
        
        // WRONG: Shallow copy (both reference same array)
        int[] shallowCopy = original;
        shallowCopy[0] = 99;
        System.out.println("Shallow copy modified original: " + original[0]); // 99
        
        // RIGHT: Deep copy
        original[0] = 1; // Reset
        int[] deepCopy = Arrays.copyOf(original, original.length);
        deepCopy[0] = 99;
        System.out.println("Deep copy doesn't affect original: " + original[0]); // 1
        
        // 3. Efficient looping
        int[] largeArray = new int[10000];
        
        // LESS EFFICIENT: length called each iteration
        for (int i = 0; i < largeArray.length; i++) {
            largeArray[i] = i;
        }
        
        // MORE EFFICIENT: Cache length
        for (int i = 0, n = largeArray.length; i < n; i++) {
            largeArray[i] = i;
        }
        
        // BEST: Use enhanced for-loop when index not needed
        int sum = 0;
        for (int value : largeArray) {
            sum += value;
        }
        
        // 4. Choosing right data structure
        System.out.println("\n=== CHOOSING DATA STRUCTURE ===");
        System.out.println("Use ARRAYS when:");
        System.out.println("  - Fixed size is known in advance");
        System.out.println("  - Need primitive type performance");
        System.out.println("  - Memory efficiency is critical");
        
        System.out.println("\nUse ARRAYLIST when:");
        System.out.println("  - Size may change dynamically");
        System.out.println("  - Need built-in methods (add, remove, etc.)");
        System.out.println("  - Working with collections framework");
        
        // 5. Memory considerations for multi-dimensional arrays
        System.out.println("\n=== MEMORY CONSIDERATIONS ===");
        int[][] regular2D = new int[1000][1000]; // 1,000,000 elements
        System.out.println("Regular 1000x1000 array: 1,000,000 ints");
        
        // More memory efficient for sparse data:
        int[][] jagged = new int[1000][];
        for (int i = 0; i < 1000; i++) {
            jagged[i] = new int[10]; // Only 10,000 total elements
        }
        System.out.println("Jagged array (1000 rows, 10 cols each): 10,000 ints");
        
        // 6. Array vs Collections decision
        System.out.println("\n=== ARRAY VS COLLECTIONS ===");
        
        // Array example (good for primitives, fixed size)
        int[] scores = new int[100];
        // Fast access: O(1)
        // Fixed size
        // Memory efficient
        
        // ArrayList example (good for objects, dynamic)
        // ArrayList scoreList = new ArrayList<>();
        // Flexible size
        // Slower for primitives (boxing/unboxing)
        // More functionality
        
        // 7. Defensive programming with arrays
        System.out.println("\n=== DEFENSIVE PROGRAMMING ===");
        
        // Method that processes array safely
        processArray(new int[]{1, 2, 3});
        processArray(null); // Handle null
        processArray(new int[0]); // Handle empty array
        
        // 8. Using varargs with arrays
        printNumbers(1, 2, 3, 4, 5);
        printNumbers(); // Empty
    }
    
    // Safe array processing method
    static void processArray(int[] arr) {
        if (arr == null) {
            System.out.println("Array is null");
            return;
        }
        
        if (arr.length == 0) {
            System.out.println("Array is empty");
            return;
        }
        
        // Process array safely
        for (int value : arr) {
            System.out.print(value + " ");
        }
        System.out.println();
    }
    
    // Using varargs (variable arguments)
    static void printNumbers(int... numbers) {
        System.out.println("Number of arguments: " + numbers.length);
        System.out.println("Values: " + Arrays.toString(numbers));
    }
}