Skip to content

Arrays

An array is a fundamental data structure in Java that stores a fixed-size, sequential collection of elements of the same data type. It is an object that holds a collection of values, accessible via an index.

  • Fixed-Size: Once an array is created, its size cannot be changed.
  • Homogeneous: All elements in an array must be of the same type (e.g., int, String, or a custom object).
  • Zero-based Indexing: Elements are accessed using a zero-based index. The first element is at index 0, the second at 1, and so on.
  • Object: In Java, arrays are objects. They inherit from java.lang.Object and have a length property that returns their size.
  • Contiguous Memory: Elements are stored in consecutive memory locations.

There are several ways to create and initialize an array in Java.

// Declaration
int[] numbers; // Preferred syntax
int numbers[]; // Alternative syntax (C-style)
// Declaration with initialization
int[] numbers = new int[5]; // Creates array of size 5
int[] numbers = {1, 2, 3, 4, 5}; // Array literal
int[] numbers = new int[]{1, 2, 3, 4, 5}; // Anonymous array
System.out.println("Array class: " + numbers.getClass().getName());
// Output: Array class: [I
System.out.println("Array length: " + numbers.length);
// Output: Array length: 5
// Multi-dimensional arrays
int[][] matrix = new int[3][4]; // 3x4 matrix
int[][] matrix = {{1, 2}, {3, 4}, {5, 6}}; // Jagged array

Since arrays have a fixed size, you cannot directly add or remove elements. The common practice is to create a new, larger (for adding) or smaller (for deleting) array and copy the relevant elements from the original array.

// Example: "Adding" an element
int[] original = {1, 2, 3};
int[] newArray = new int[original.length + 1];
// Copy elements from the original array
System.arraycopy(original, 0, newArray, 0, original.length);
// Add the new element
newArray[newArray.length - 1] = 4;
System.out.println("New array: " + java.util.Arrays.toString(newArray));
// Output: New array: [1, 2, 3, 4]

Elements are accessed and modified using their index.

int[] data = {10, 20, 30, 40, 50};
// Accessing an element
int firstElement = data[0];
System.out.println("First element: " + firstElement);
// Output: First element: 10
// Updating an element
data[0] = 100;
System.out.println("Updated first element: " + data[0]);
// Output: Updated first element: 100
  • Single-dimensional arrays: Basic form, like int[]
  • Multidimensional arrays: “Arrays of arrays,”
  • Jagged arrays: Each sub-array can have a different length
  • Object arrays: Can store objects of any type
// Single-dimensional array
int[] singleDimArray = {1, 2, 3};
// Multidimensional array 2x2 matrix
int[][] multiDimArray = {{1, 2}, {3, 4}};
// Iterating through the matrix
for (int i = 0; i < multiDimArray.length; i++) {
for (int j = 0; j < multiDimArray[i].length; j++) {
System.out.print(multiDimArray[i][j] + " ");
}
System.out.println();
}
// Jagged array
int[][] jaggedArray = {{1, 2}, {3, 4, 5}};
// Object array
Object[] objectArray = {1, "Hello", true}; //not recommended
class Student {
String name;
int id;
Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "ID: " + id + ", Name: " + name;
}
}
public class ObjectArray {
public static void main(String[] args) {
Student[] students = new Student[3]; //Object array
students[0] = new Student(1, "Alice");
students[1] = new Student(2, "Bob");
students[2] = new Student(3, "Charlie");
for (Student s : students) {
System.out.println(s);
}
// Output:
// ID: 1, Name: Alice
// ID: 2, Name: Bob
// ID: 3, Name: Charlie
}
}

The java.util.Arrays class provides static utility methods for common array operations.

int[] numbers = {5, 1, 4, 2, 3};
int[][] 2dArray = {{1, 2}, {3, 4}, {5, 6}};
// Classic for loop
for (int i = 0; i < numbers.length; i++) { }
// Enhanced for loop (foreach)
for (int num : numbers) { }
//Printing 2D arrays
System.out.println(Arrays.deepToString(2dArray));
//Sorts the array in ascending order
Arrays.sort(numbers);
System.out.println("Sorted array: " + Arrays.toString(numbers));
// Output: Sorted array: [1, 2, 3, 4, 5]
int[] largeArray = {9, 5, 2, 7, 1, 8, 3, 6, 4};
Arrays.parallelSort(largeArray); // Efficient for large datasets
System.out.println("Parallel sorted array: " + Arrays.toString(largeArray));
// Output: Parallel sorted array: [1, 2, 3, 4, 5, 6, 7, 8, 9]
// Binary search (array must be sorted)
int index = Arrays.binarySearch(numbers, 5);
System.out.println("Index of 5: " + index);
// Copying arrays
int[] original = {1, 2, 3, 4, 5};
// Using clone() - shallow copy
int[] copy1 = original.clone();
//Creates a new array of a specified length, copying elements from the original.
int[] copy2 = Arrays.copyOf(original, original.length);
//Copies a specified range of an array into a new array.
int[] copy3 = Arrays.copyOfRange(original, 1, 4);
// Copy elements from the original array
//System.arraycopy(src, srcPos, dest, destPos, length);
int[] copy4 = new int[original.length];
System.arraycopy(original, 0, copy4, 0, original.length);
// Manual copy
int[] copy5 = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy5[i] = original[i];
}
// Filling array
int[] filled = new int[5];
Arrays.fill(filled, 10);
System.out.println("Filled array: " + Arrays.toString(filled));
// Output: Filled array: [10, 10, 10, 10, 10]
// Comparing arrays
boolean areEqual = Arrays.equals(numbers, copy1);
System.out.println("Arrays equal: " + areEqual);
// Output: Arrays equal: true
// Converting to string
System.out.println("Array as string: " + Arrays.toString(numbers));
// Output: Array as string: [1, 2, 3, 5, 8, 9]
// Converting to stream
Arrays.stream(numbers)
.forEach(System.out::println);
// Output:
// 1
// 2
// 3
// 5
// 8
// 9
String[] languages = {"Java", "Python", "JavaScript"};
// Using streams to filter and print
Arrays.stream(languages)
.filter(lang -> lang.startsWith("J"))
.forEach(System.out::println);
// Output:
// Java
// JavaScript
  • Use Arrays.sort() with Collections.reverseOrder() as the second argument.
  • Note: This does not work for primitive types (like int[]).
  • All these methods will work only for Integer[]
import java.util.Arrays;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
Integer[] arr = {5, 2, 1, 8, 10};
Arrays.sort(arr); // Sorts in ascending order
Arrays.sort(arr, (a, b) -> Integer.compare(a, b)); // Sorts in ascending order
Arrays.sort(arr, Comparator.naturalOrder()); // does the same thing as above.
System.out.println(Arrays.toString(arr)); // Output: [1, 2, 5, 8, 10]
Arrays.sort(arr, Collections.reverseOrder()); // Sorts in descending order
Arrays.sort(arr, (a, b) -> Integer.compare(b, a)); // Sorts in descending order
Arrays.sort(arr, Comparator.reverseOrder()); // does the same thing as above.
System.out.println(Arrays.toString(arr)); // Output: [10, 8, 5, 2, 1]
}
}
  • Reversing in-place is necessary because Java does not provide a direct way to sort primitive arrays in descending order
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr = {5, 2, 1, 8, 10};
Arrays.sort(arr); // Sorts in ascending order
// Now reverse in-place
for(int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
System.out.println(Arrays.toString(arr)); // Output: [10, 8, 5, 2, 1]
}
}

Then how this 2D array works?

int[][] array= {
{1, 5},
{13, 1},
{12, 100},
{12, 85}
};
Arrays.sort(array, (a, b) -> Integer.compare(a[1], b[1])); // for ascending order
Arrays.sort(array, (b, a) -> Integer.compare(a[1], b[1])); // for descending order

int[][] is an array of references (int[]), not primitives.

Even though int[][] might look like a primitive 2D array, it’s actually an array of objects — specifically, each int[] inside it is a reference type (an object in memory).

So, int[][] is treated as:

int[][] array = new int[][] {
new int[] {1, 5},
new int[] {13, 1},
...
};

Java allows custom comparators for reference types. Arrays.sort(T[] a, Comparator<? super T> c) works when T is a reference type — which int[] is.

So when you write:

Arrays.sort(array, (a, b) -> Integer.compare(a[1], b[1]));

You are:

  • Sorting an array of int[]
  • Using a comparator that compares a[1] and b[1] (i.e., comparing the second elements of subarrays)
  • This is perfectly legal and very common in Java.

Sorting int[] (Primitive Array) in Descending Order using Streams

Section titled “Sorting int[] (Primitive Array) in Descending Order using Streams”
int[] sortedArr = Arrays.stream(arr)
.boxed()
.sorted(Collections.reverseOrder())
.mapToInt(Integer::intValue)
.toArray();

Sorting Reference:

Student.java
class Student implements Comparable<Student> {
public String name;
public int rollNo;
Student(String name, int rollNo) {
this.name = name;
this.rollNo = rollNo;
}
public int getRollNo() {
return rollNo;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name + " - " + rollNo;
}
@Override
public int compareTo(Student o) {
return this.rollNo - o.rollNo; // Sort by roll number
}
}
Main.java
public void main() {
Student[] students = new Student[] {
new Student("Alice", 5),
new Student("Bob", 2),
new Student("Charlie", 8)
};
// Sort using Comparable (by rollNo) - default sorting defined in Student class
Arrays.sort(students);
// Sort ascending by rollNo
Arrays.sort(students, Comparator.comparingInt(s -> s.rollNo));
System.out.println("Ascending by rollNo: " + Arrays.toString(students));
// Sort descending by rollNo
// Add explicit type for lambda parameter for reversed sorting
Arrays.sort(students, Comparator.comparingInt((Student s) -> s.rollNo).reversed());
Arrays.sort(students, Comparator.comparingInt(Student::getRollNo).reversed());
// ❌ Error: rollNo cannot be resolved
Arrays.sort(students, Comparator.comparingInt(s -> s.rollNo).reversed());
// Sorting by Multiple Fields
Arrays.sort(students, Comparator
.comparingInt((Student s) -> s.rollNo)
.thenComparing(s -> s.name)
);
// reversed sorting by multiple fields
Arrays.sort(students, Comparator
.comparingInt((Student s) -> s.rollNo) //explicit type for lambda parameter required. Otherwise, it will not compile
.thenComparing(s -> s.name)
.reversed()
);
}
// Shallow copy - references are copied, not objects
Student[] original = {new Student("Alice", 20)};
Student[] copy = original.clone();
copy[0].setAge(25); // This affects original array too!
// Deep copy - create new objects
Student[] deepCopy = new Student[original.length];
for (int i = 0; i < original.length; i++) {
deepCopy[i] = new Student(original[i].getName(), original[i].getAge());
}
  • Arrays are covariant: Object[] objs = new String; is allowed.
  • Can lead to ArrayStoreException at runtime.
// Arrays are covariant - if B extends A, then B[] is a subtype of A[]
Object[] objects = new String[10]; // Legal
objects[0] = "Hello"; // OK
objects[1] = 42; // Runtime exception: ArrayStoreException
// Cannot create generic arrays directly
// List<String>[] lists = new List<String>[10]; // Compilation error
// Workaround
@SuppressWarnings("unchecked")
List<String>[] lists = (List<String>[]) new List[10];
import java.lang.reflect.Array;
public static Object createArray(Class<?> componentType, int length) {
return Array.newInstance(componentType, length);
}
// Usage
int[] intArray = (int[]) createArray(int.class, 5);
String[] stringArray = (String[]) createArray(String.class, 10);
  1. Use ArrayList for Dynamic Size: If you need a collection that can grow or shrink, use java.util.ArrayList instead of an array.
  2. Check for null: Always ensure an array is not null before accessing its length or elements to avoid a NullPointerException.
  3. Use Enhanced For-Loop: For simple iteration without needing the index, the enhanced for-loop is cleaner and less error-prone.
  4. Leverage java.util.Arrays: Use the utility methods for common tasks like sorting, searching, and copying.
  5. Declare with Type: Use int[] arr instead of int arr[] for better readability.
  1. ArrayIndexOutOfBoundsException: Accessing an array with an invalid index (less than 0 or greater than or equal to array.length).
  2. Fixed Size Limitation: Forgetting that arrays cannot be resized, leading to inefficient solutions where arrays are repeatedly created and copied.
  3. Shallow Copy: When copying an array of objects, only the references are copied, not the objects themselves. Modifying an object in one array will affect the other.
  4. Incorrect Equality Check: Using arr1 == arr2 compares object references, not contents. Use Arrays.equals(arr1, arr2) to compare contents.

1. What is the difference between an array and an ArrayList?

  • Size: Arrays have a fixed size, while ArrayList has a dynamic size.
  • Performance: Arrays are generally faster because they provide direct memory access, whereas ArrayList involves overhead for resizing and method calls.
  • Type: Arrays can hold both primitives (int, char) and objects, while ArrayList can only hold objects (it uses wrapper classes like Integer for primitives).

2. What is the default value of elements in an array?

If an array is instantiated without being explicitly initialized, its elements are assigned default values based on their type:

  • 0 for numeric types (byte, short, int, long, float, double)
  • \u0000 for char
  • false for boolean
  • null for object types (e.g., String)

3. Can an array have a size of 0?

Yes, an array can be created with a size of zero. This is often useful as a return value for methods that are expected to return an array but have no results, avoiding the need to return null.

int[] emptyArray = new int[0];
System.out.println("Length of empty array: " + emptyArray.length);
// Output: Length of empty array: 0

4. Why does Java not support sizeof() for arrays like C++?

Java manages memory automatically. The length of an array is stored as a property (.length), which provides the size without needing a sizeof operator.

5. Explain array covariance in Java.

Array covariance means that if S is a subtype of T, then S[] is a subtype of T[]. For example, a String[] can be assigned to an Object[] variable. However, this can lead to a runtime ArrayStoreException if you try to insert an incompatible type into the array.

6. How do generics and arrays interact?

You cannot create an array of a parameterized type (e.g., new ArrayList<String>[10]). This is due to type erasure, where generic type information is lost at runtime, which conflicts with the runtime type safety checks that arrays require.

1. How do you find a duplicate number in an integer array?

One common approach is to use a HashSet to keep track of the numbers you’ve seen. If you encounter a number that’s already in the set, it’s a duplicate.

import java.util.HashSet;
import java.util.Set;
public int findDuplicate(int[] nums) {
Set<Integer> seen = new HashSet<>();
for (int num : nums) {
if (!seen.add(num)) {
return num; // Found the duplicate
}
}
return -1; // No duplicate found
}

2. How do you reverse an array in-place?

Iterate from both ends of the array towards the center, swapping elements at each step.

public void reverseArray(int[] arr) {
int start = 0;
int end = arr.length - 1;
while (start < end) {
// Swap elements
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
// Move pointers
start++;
end--;
}
}

3. How do you find the largest and smallest number in an unsorted array?

Iterate through the array, keeping track of the minimum and maximum values found so far.

public void findMinMax(int[] nums) {
if (nums == null || nums.length == 0) return;
int min = nums[0];
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] < min) {
min = nums[i];
}
if (nums[i] > max) {
max = nums[i];
}
}
System.out.println("Minimum: " + min);
System.out.println("Maximum: " + max);
}
  • Data Storage: Storing fixed-size collections of data, such as daily temperature readings for a month or the scores of students in a class.
  • Image Processing: A 2D array can represent an image, where each element stores the color value of a pixel.
  • Game Development: Using arrays to create game boards, grids, or to manage a collection of game objects.
  • Performance-Critical Applications: Used in algorithms and low-level programming where performance and direct memory control are crucial.