Array Fundamentals and Initialization
In Java, an array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created and cannot be changed thereafter. Arrays are stored in a contiguous block of memory, allowing for efficient random access via an index.
Declaring and Instantiating Arrays
The syntax for declaring an array involves specifying the type followed by square brackets and the variable name. Instantiation allocates memory for the array using the new keyword.
// Syntax: Type[] arrayName = new Type[size];
int[] numbers = new int[10]; // An integer array with capacity for 10 elements
String[] names = new String[5]; // A String array with capacity for 5 elements
double[] values = new double[3]; // A double array with capacity for 3 elements
Initialization Techniques
There are three primary ways to initialize arrays in Java:
- Dynamic Initialization: Specify the length, and the system assigns default values (e.g., 0 for integers,
falsefor booleans,nullfor objects).
int[] data = new int[5]; // Elements are 0, 0, 0, 0, 0
- Static Initialization: Provide the initial values at the time of creation. The compiler determines the length based on the number of elements provided.
int[] primes = new int[]{2, 3, 5, 7, 11};
String[] colors = {"Red", "Green", "Blue"}; // Shorthand syntax
- Split Initialization: Declare the reference first and assign the memory later. Note that the shorthand syntax
{...}cannot be used in a split declaration; you must usenew Type[]{...}.
int[] scores;
scores = new int[]{90, 85, 95}; // Valid
// scores = {90, 85, 95}; // Compilation Error
Accessing and Iterating
Elements are accessed using a zero-based index. Attempting to access an index outside the range [0, length-1] results in an ArrayIndexOutOfBoundsException.
int[] series = {10, 20, 30, 40};
System.out.println(series[1]); // Outputs: 20
series[2] = 35; // Modify element at index 2
// Iteration using a standard for-loop
for (int i = 0; i < series.length; i++) {
System.out.print(series[i] + " ");
}
// Iteration using for-each loop
for (int item : series) {
System.out.print(item + " ");
}
Memory Management and Reference Types
Understanding how arrays interact with the Java Virtual Machine (JVM) memory is crucial for managing data effectively.
JVM Memory Layout
The JVM divides memory into distinct regions. For array operations, the most relevant are:
- Stack: Stores local variables and object references. Execution context is managed here.
- Heap: Stores actual objects and array data. Memory allocated via
newresides here.
Primitive vs. Reference Types
When you create an array of primitives (e.g., int[]), the array variable on the stack holds a reference (address) to the contiguous block of memory on the heap where the integers are stored.
public void referenceExample() {
int[] first = new int[]{1, 2, 3};
int[] second = new int[]{100, 200};
// 'first' now refers to the same object as 'second'
first = second;
first[0] = 999;
// This prints 999, proving both references point to the same array
System.out.println(second[0]);
}
Understanding Null
If an array reference is declared but not assigned to an object, it defaults to null. Attempting to access indices or the length of a null reference throws a NullPointerException.
Array Operations and Algorithms
Arrays as Parameters and Return Values
Since arrays are objects, passing an array to a method passes the reference. Therefore, changes made to the array inside the method affect the original array. Arrays can also be returned from methods.
public static int[] generateFibonacci(int count) {
if (count <= 0) return null;
int[] seq = new int[count];
seq[0] = 1;
if (count > 1) seq[1] = 1;
for (int i = 2; i < count; i++) {
seq[i] = seq[i - 1] + seq[i - 2];
}
return seq;
}
Utility Methods: Conversion and Copying
The java.util.Arrays class provides helper methods.
import java.util.Arrays;
int[] rawData = {5, 1, 4, 2, 3};
// Convert to String for readable output
System.out.println(Arrays.toString(rawData)); // [5, 1, 4, 2, 3]
// Create a copy of the array
int[] backup = Arrays.copyOf(rawData, rawData.length);
// Copy a specific range (from index 1 to 3)
int[] partial = Arrays.copyOfRange(rawData, 1, 4);
Calculating Average
public static double calculateAverage(int[] nums) {
long sum = 0;
for (int n : nums) {
sum += n;
}
return (double) sum / nums.length;
}
Searching Algorithms
Linear Search
Checks every element sequentially. Works on unsorted arrays but is inefficient for large datasets (O(n)).
public static int findIndex(int[] container, int target) {
for (int i = 0; i < container.length; i++) {
if (container[i] == target) {
return i;
}
}
return -1; // Not found
}
Binary Search
Requires a sorted array. Repeatedly divides the search interval in half (O(log n)).
public static int binarySearch(int[] sortedArr, int key) {
int low = 0;
int high = sortedArr.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (sortedArr[mid] == key) {
return mid;
} else if (sortedArr[mid] < key) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}
Sorting Algorithms
Bubble Sort
A simple comparison-based algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order.
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// Swap arr[j] and arr[j+1]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
// Built-in efficient sort
Arrays.sort(arr);
Reversing an Array
Swaps elements symmetrically positioned around the center.
public static void reverse(int[] input) {
int start = 0;
int end = input.length - 1;
while (start < end) {
int temp = input[start];
input[start] = input[end];
input[end] = temp;
start++;
end--;
}
}
Two-Dimensional Arrays
A two-dimensional array in Java is essentially an array of arrays. It allows for the storage of data in a grid or matrix format.
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Iterating over a 2D array
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[row].length; col++) {
System.out.print(matrix[row][col] + "\t");
}
System.out.println();
}