Arrays: Working with Collections

Duration: 45 min

Arrays: Working with Collections

Duration: 45 min

Introduction

Arrays are fundamental data structures that store multiple values of the same type in a single variable. They're the bridge between simple variables and more complex data structures. Arrays appear everywhere: storing inventory in a store system, managing pixels in an image, holding game tiles on a board, or collecting sensor readings.

This module covers array declaration and initialization, iteration techniques, multi-dimensional arrays, the Arrays utility class, and introduces ArrayList for dynamic sizing. You'll learn when to use arrays versus ArrayLists, and common patterns for data processing.

Array Declaration and Initialization

Arrays in Java are fixed-size collections. The syntax uses square brackets and requires a size at creation time.

public class ArrayBasics {
    public static void main(String[] args) {
        // Declaration and initialization - size must be specified
        int[] numbers = new int[5];  // Creates array of 5 integers (all 0)
        
        // Initialization with values
        String[] fruits = {"Apple", "Banana", "Cherry"};  // Size inferred from values
        
        // Empty braces means default values
        double[] temps = new double[7];  // All elements are 0.0
        
        // Accessing elements - indices start at 0
        fruits[0] = "Apricot";  // Modify element
        System.out.println("First fruit: " + fruits[0]);
        System.out.println("Array length: " + fruits.length);  // Property, not method
        
        // Java arrays are objects - int[] is reference type
        int[] arr1 = {1, 2, 3};
        int[] arr2 = arr1;  // Both reference same array
        arr2[0] = 99;
        System.out.println(arr1[0]);  // Also 99 - same array!
        
        // Copy creates new array
        int[] arr3 = new int[arr1.length];
        System.arraycopy(arr1, 0, arr3, 0, arr1.length);
        arr3[0] = 50;  // Doesn't affect arr1
        System.out.println(arr1[0]);  // Still 99
    }
}

Array indices run from 0 to length-1. Accessing beyond this range throws an ArrayIndexOutOfBoundsException. The .length property (not method) gives the fixed size of the array.

Array Iteration

Multiple ways to iterate arrays—choose based on what information you need.

public class ArrayIteration {
    public static void main(String[] args) {
        int[] scores = {85, 90, 78, 95, 88};
        
        // Traditional for loop - when you need the index
        System.out.println("Traditional for loop:");
        for (int i = 0; i < scores.length; i++) {
            System.out.println("Index " + i + ": " + scores[i]);
        }
        
        // Enhanced for loop - cleaner when you don't need index
        System.out.println("\nEnhanced for loop:");
        for (int score : scores) {
            System.out.println("Score: " + score);
        }
        
        // While loop with index
        System.out.println("\nWhile loop:");
        int i = 0;
        while (i < scores.length) {
            System.out.println(scores[i]);
            i++;
        }
        
        // Processing elements - calculate average
        int sum = 0;
        for (int score : scores) {
            sum += score;
        }
        double average = sum / (double) scores.length;
        System.out.println("Average: " + average);
        
        // Finding specific values
        int target = 90;
        for (int j = 0; j < scores.length; j++) {
            if (scores[j] == target) {
                System.out.println("Found " + target + " at index " + j);
            }
        }
    }
}

Use enhanced for loops when you only need values. Use traditional for loops when you need indices for modification, comparison with adjacent elements, or early termination logic.

Multi-Dimensional Arrays

Arrays of arrays create matrices and grids. Each element is itself an array.

public class MultiDimensionalArrays {
    public static void main(String[] args) {
        // 2D array - 3 rows, 4 columns
        int[][] matrix = new int[3][4];
        
        // Initialize with values
        int[][] grid = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        // Accessing elements - [row][column]
        System.out.println(grid[1][2]);  // 6 (row 1, column 2)
        grid[0][0] = 10;
        
        // Iterating 2D arrays
        System.out.println("2D Array contents:");
        for (int row = 0; row < grid.length; row++) {
            for (int col = 0; col < grid[row].length; col++) {
                System.out.printf("%2d ", grid[row][col]);
            }
            System.out.println();
        }
        
        // Using enhanced for with 2D arrays
        System.out.println("\nUsing enhanced for:");
        for (int[] row : grid) {
            for (int value : row) {
                System.out.printf("%2d ", value);
            }
            System.out.println();
        }
        
        // Jagged arrays - rows can have different lengths
        int[][] jagged = {
            {1, 2, 3},
            {4, 5},
            {6}
        };
        
        for (int[] row : jagged) {
            for (int value : row) {
                System.out.print(value + " ");
            }
            System.out.println();
        }
        
        // 3D array
        int[][][] cube = new int[2][3][4];  // 2 × 3 × 4 grid
        cube[0][1][2] = 42;
    }
}

Multi-dimensional arrays are arrays of references to other arrays. In a jagged array, rows can have different lengths—Java only requires the first dimension to be rectangular.

Arrays Utility Class

The Arrays class provides static methods for common operations on arrays.

import java.util.Arrays;

public class ArraysUtility { public static void main(String[] args) { int[] numbers = {64, 34, 25, 12, 22, 11, 90}; // Sorting Arrays.sort(numbers); System.out.println("Sorted: " + Arrays.toString(numbers)); // Searching (requires sorted array) int index = Arrays.binarySearch(numbers, 25); System.out.println("Index of 25: " + index); // Filling int[] filled = new int[5]; Arrays.fill(filled, 7); System.out.println("Filled array: " + Arrays.toString(filled)); // Copying int[] original = {1, 2, 3, 4, 5}; int[] copy = Arrays.copyOf(original, 3); // First 3 elements System.out.println("Copied: " + Arrays.toString(copy)); int[] extended = Arrays.copyOf(original, 8); // Pad with zeros System.out.println("Extended: " + Arrays.toString(extended)); // Comparing arrays int[] arr1 = {1, 2, 3}; int[] arr2 = {1, 2, 3}; int[] arr3 = {1, 2, 4}; System.out.println("arr1 equals arr2: " + Arrays.equals(arr1, arr2)); System.out.println("arr1 equals arr3: " + Arrays.equals(arr1, arr3)); // Converting to List Integer[] boxed = {1, 2, 3}; java.util.List list = Arrays.asList(boxed); System.out.println("As list: " + list); } }

Arrays.toString() provides readable output. Arrays.sort() uses optimized algorithms (TimSort for objects, QuickSort for primitives). Arrays.binarySearch() requires a sorted array and returns negative index if not found.

ArrayList - Dynamic Arrays

ArrayList grows automatically, unlike fixed-size arrays. It's part of the Collections framework and is more flexible for real-world programs.

import java.util.ArrayList;

public class ArrayListDemo { public static void main(String[] args) { // ArrayList of Strings ArrayList cities = new ArrayList<>(); // Adding elements cities.add("New York"); cities.add("Los Angeles"); cities.add("Chicago"); // Accessing System.out.println("First city: " + cities.get(0)); System.out.println("Size: " + cities.size()); // 3 // Modifying cities.set(1, "San Francisco"); // Removing cities.remove(2); // Remove by index cities.remove("New York"); // Remove by value // Checking if contains if (cities.contains("Chicago")) { System.out.println("Found Chicago"); } // Iterating for (String city : cities) { System.out.println("City: " + city); } // ArrayList of primitives requires wrapper class ArrayList scores = new ArrayList<>(); scores.add(85); // Auto-boxing converts int to Integer scores.add(90); scores.add(78); int total = 0; for (int score : scores) { // Auto-unboxing converts Integer to int total += score; } // Converting ArrayList to array String[] citiesArray = cities.toArray(new String[0]); System.out.println("As array: " + Arrays.toString(citiesArray)); } }

ArrayList uses generics with syntax. Use <> for type inference (diamond operator). ArrayList is slower than arrays for raw performance but faster for development and flexibility.

Common Array Patterns

Pattern 1: Finding Maximum

int[] temps = {72, 85, 68, 91, 78};
int max = temps[0];
for (int temp : temps) {
    if (temp > max) max = temp;
}
System.out.println("Hottest: " + max);

Pattern 2: Removing Duplicates

int[] data = {1, 2, 2, 3, 3, 3, 4};
ArrayList unique = new ArrayList<>();
for (int value : data) {
    if (!unique.contains(value)) {
        unique.add(value);
    }
}

Pattern 3: Reversing

int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length / 2; i++) {
    int temp = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}

Arrays vs ArrayList

| Arrays | ArrayList | |--------|-----------| | Fixed size | Dynamic size | | Primitives supported | Only objects | | Slightly faster | More flexible | | Use [] syntax | Use .get() / .set() | | Use when size is known | Use when size varies |

Advanced Array Techniques

Searching and Filtering

public class ArraySearch {
    // Linear search
    public static int findFirst(int[] array, int target) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == target) return i;
        }
        return -1;
    }
    
    // Count occurrences
    public static int countOccurrences(int[] array, int target) {
        int count = 0;
        for (int value : array) {
            if (value == target) count++;
        }
        return count;
    }
    
    // Filter elements (create new array)
    public static int[] getEvenNumbers(int[] array) {
        ArrayList evens = new ArrayList<>();
        for (int num : array) {
            if (num % 2 == 0) {
                evens.add(num);
            }
        }
        int[] result = new int[evens.size()];
        for (int i = 0; i < evens.size(); i++) {
            result[i] = evens.get(i);
        }
        return result;
    }
}

Working with Object Arrays

public class ObjectArrays {
    static class Student {
        String name;
        double gpa;
        Student(String name, double gpa) {
            this.name = name;
            this.gpa = gpa;
        }
    }
    
    public static void displayStudents(Student[] students) {
        for (Student student : students) {
            System.out.printf("%s: %.2f%n", student.name, student.gpa);
        }
    }
    
    public static double averageGPA(Student[] students) {
        if (students.length == 0) return 0;
        double sum = 0;
        for (Student student : students) {
            sum += student.gpa;
        }
        return sum / students.length;
    }
}

ArrayList Advanced Operations

import java.util.ArrayList;
import java.util.Collections;

public class ArrayListAdvanced { public static void main(String[] args) { ArrayList numbers = new ArrayList<>(); numbers.add(5); numbers.add(2); numbers.add(8); numbers.add(2); // Sorting Collections.sort(numbers); System.out.println(numbers); // [2, 2, 5, 8] // Finding max/min int max = Collections.max(numbers); int min = Collections.min(numbers); // Reversing Collections.reverse(numbers); System.out.println(numbers); // [8, 5, 2, 2] // Removing duplicates ArrayList unique = new ArrayList<>(new java.util.HashSet<>(numbers)); // Checking containment System.out.println(numbers.contains(5)); // true } }

Array vs ArrayList Comprehensive Comparison

| Aspect | Array | ArrayList | |--------|-------|-----------| | Type | Fixed-size collection | Dynamic collection | | Creation | int[] arr = {1, 2, 3}; | ArrayList list = new ArrayList<>(); | | Size | arr.length (property) | list.size() (method) | | Adding | Index assignment only | add(), add(index, value) | | Removing | Manual array copy | remove() method | | Sorting | Arrays.sort() | Collections.sort() | | Searching | Arrays.binarySearch() | list.contains(), iterate | | Memory | Fixed, allocated | Dynamic, grows as needed | | Performance | O(1) access | O(1) access | | Primitives | Supported directly | Requires wrapper classes | | Null values | Can store nulls | Can store nulls |

Common Array Pitfalls

public class ArrayPitfalls {
    public static void main(String[] args) {
        // Pitfall 1: Null pointer on uninitialized array
        int[] arr = null;
        // arr[0] = 5;  // NullPointerException
        
        // Pitfall 2: Index out of bounds
        int[] nums = {1, 2, 3};
        // nums[5] = 10;  // ArrayIndexOutOfBoundsException
        
        // Pitfall 3: Reference vs copy
        int[] original = {1, 2, 3};
        int[] reference = original;
        reference[0] = 99;
        System.out.println(original[0]);  // 99 - both changed!
        
        // Pitfall 4: ArrayList generics type erasure
        ArrayList stringList = new ArrayList<>();
        // Cannot do: ArrayList[] array = new ArrayList[10];
    }
}

Key Takeaways

1. Arrays store multiple values of same type with fixed size 2. Indices start at 0 and go to length-1 3. Enhanced for loops are cleaner for simple iteration 4. Multi-dimensional arrays are arrays of arrays 5. Arrays utility class provides sorting, searching, copying 6. ArrayList is a dynamic alternative that grows automatically 7. Use arrays for fixed-size collections; ArrayList for variable sizes 8. Be aware of reference vs copy when assigning arrays 9. Object arrays store references to objects, not objects themselves 10. ArrayList provides convenient methods for searching and sorting

Quiz

Question 1: What's the output?

int[] arr = {10, 20, 30, 40};
System.out.println(arr[2]);
  • A) 10
  • B) 20
  • C) 30 ✓
  • D) ArrayIndexOutOfBoundsException

Question 2: Which correctly declares a 2D array?

  • A) int[] arr = new int[3][4];
  • B) int[][] arr = new int[3][4];
  • C) int[3,4] arr = new int[3][4];
  • D) Both A and B are correct

Question 3: What does arr.length return for an array?

  • A) The maximum value in the array
  • B) The size/number of elements ✓
  • C) A method that must be called with arr.length()
  • D) The index of the last element

Question 4: When would you use ArrayList instead of array?

  • A) When size is known and fixed
  • B) When you need maximum performance
  • C) When size may change during execution ✓
  • D) When storing primitive types

Question 5: What's the output?

int[] numbers = {1, 2, 3, 4, 5};
Arrays.sort(numbers);
int index = Arrays.binarySearch(numbers, 3);
System.out.println(index);
  • A) 0
  • B) 1
  • C) 2 ✓
  • D) -1

Question 6: Which creates an ArrayList that can hold Strings?

  • A) ArrayList strings = new ArrayList();
  • B) ArrayList strings = new ArrayList<>();
  • C) ArrayList strings = new ArrayList();
  • D) Both B and C are correct ✓