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.
Core Concepts
Section titled “Core Concepts”- 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 at1, and so on. - Object: In Java, arrays are objects. They inherit from
java.lang.Objectand have alengthproperty that returns their size. - Contiguous Memory: Elements are stored in consecutive memory locations.
Creating and Initializing Arrays
Section titled “Creating and Initializing Arrays”There are several ways to create and initialize an array in Java.
// Declarationint[] numbers; // Preferred syntaxint numbers[]; // Alternative syntax (C-style)
// Declaration with initializationint[] numbers = new int[5]; // Creates array of size 5int[] numbers = {1, 2, 3, 4, 5}; // Array literalint[] numbers = new int[]{1, 2, 3, 4, 5}; // Anonymous array
System.out.println("Array class: " + numbers.getClass().getName());// Output: Array class: [ISystem.out.println("Array length: " + numbers.length);// Output: Array length: 5
// Multi-dimensional arraysint[][] matrix = new int[3][4]; // 3x4 matrixint[][] matrix = {{1, 2}, {3, 4}, {5, 6}}; // Jagged arrayManipulating Array Elements
Section titled “Manipulating Array Elements”Adding or Deleting Elements
Section titled “Adding or Deleting Elements”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 elementint[] original = {1, 2, 3};int[] newArray = new int[original.length + 1];
// Copy elements from the original arraySystem.arraycopy(original, 0, newArray, 0, original.length);
// Add the new elementnewArray[newArray.length - 1] = 4;
System.out.println("New array: " + java.util.Arrays.toString(newArray));// Output: New array: [1, 2, 3, 4]Accessing and Updating Elements
Section titled “Accessing and Updating Elements”Elements are accessed and modified using their index.
int[] data = {10, 20, 30, 40, 50};
// Accessing an elementint firstElement = data[0];System.out.println("First element: " + firstElement);// Output: First element: 10
// Updating an elementdata[0] = 100;System.out.println("Updated first element: " + data[0]);// Output: Updated first element: 100Array Types
Section titled “Array Types”- 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 arrayint[] singleDimArray = {1, 2, 3};
// Multidimensional array 2x2 matrixint[][] multiDimArray = {{1, 2}, {3, 4}};
// Iterating through the matrixfor (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 arrayint[][] jaggedArray = {{1, 2}, {3, 4, 5}};
// Object arrayObject[] 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 }}Frequently Used Array Operations
Section titled “Frequently Used Array Operations”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 loopfor (int i = 0; i < numbers.length; i++) { }
// Enhanced for loop (foreach)for (int num : numbers) { }
//Printing 2D arraysSystem.out.println(Arrays.deepToString(2dArray));
//Sorts the array in ascending orderArrays.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 datasetsSystem.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 copyint[] 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 copyint[] copy5 = new int[original.length];for (int i = 0; i < original.length; i++) { copy5[i] = original[i];}
// Filling arrayint[] 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 arraysboolean areEqual = Arrays.equals(numbers, copy1);System.out.println("Arrays equal: " + areEqual);// Output: Arrays equal: true
// Converting to stringSystem.out.println("Array as string: " + Arrays.toString(numbers));// Output: Array as string: [1, 2, 3, 5, 8, 9]
// Converting to streamArrays.stream(numbers) .forEach(System.out::println);// Output:// 1// 2// 3// 5// 8// 9
String[] languages = {"Java", "Python", "JavaScript"};
// Using streams to filter and printArrays.stream(languages) .filter(lang -> lang.startsWith("J")) .forEach(System.out::println);// Output:// Java// JavaScriptSorting
Section titled “Sorting”Sorting Integer[] Using Built-in Methods
Section titled “Sorting Integer[] Using Built-in Methods”- 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] }}Sorting int[] (Primitive Array)
Section titled “Sorting int[] (Primitive Array)”- 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 orderArrays.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:
Sorting Objects
Section titled “Sorting Objects”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 }}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() );
}Advanced Topics
Section titled “Advanced Topics”Shallow vs Deep Copy
Section titled “Shallow vs Deep Copy”// Shallow copy - references are copied, not objectsStudent[] original = {new Student("Alice", 20)};Student[] copy = original.clone();copy[0].setAge(25); // This affects original array too!
// Deep copy - create new objectsStudent[] deepCopy = new Student[original.length];for (int i = 0; i < original.length; i++) { deepCopy[i] = new Student(original[i].getName(), original[i].getAge());}Array Covariance
Section titled “Array Covariance”- 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]; // Legalobjects[0] = "Hello"; // OKobjects[1] = 42; // Runtime exception: ArrayStoreExceptionGeneric Arrays Limitation
Section titled “Generic Arrays Limitation”// 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];Array Reflection
Section titled “Array Reflection”import java.lang.reflect.Array;
public static Object createArray(Class<?> componentType, int length) { return Array.newInstance(componentType, length);}
// Usageint[] intArray = (int[]) createArray(int.class, 5);String[] stringArray = (String[]) createArray(String.class, 10);Best Practices
Section titled “Best Practices”- Use
ArrayListfor Dynamic Size: If you need a collection that can grow or shrink, usejava.util.ArrayListinstead of an array. - Check for
null: Always ensure an array is notnullbefore accessing itslengthor elements to avoid aNullPointerException. - Use Enhanced For-Loop: For simple iteration without needing the index, the enhanced for-loop is cleaner and less error-prone.
- Leverage
java.util.Arrays: Use the utility methods for common tasks like sorting, searching, and copying. - Declare with Type: Use
int[]arr instead ofint arr[]for better readability.
Common Pitfalls
Section titled “Common Pitfalls”ArrayIndexOutOfBoundsException: Accessing an array with an invalid index (less than 0 or greater than or equal toarray.length).- Fixed Size Limitation: Forgetting that arrays cannot be resized, leading to inefficient solutions where arrays are repeatedly created and copied.
- 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.
- Incorrect Equality Check: Using
arr1 == arr2compares object references, not contents. UseArrays.equals(arr1, arr2)to compare contents.
Conceptual Questions and Answers
Section titled “Conceptual Questions and Answers”1. What is the difference between an array and an ArrayList?
- Size: Arrays have a fixed size, while
ArrayListhas a dynamic size. - Performance: Arrays are generally faster because they provide direct memory access, whereas
ArrayListinvolves overhead for resizing and method calls. - Type: Arrays can hold both primitives (
int,char) and objects, whileArrayListcan only hold objects (it uses wrapper classes likeIntegerfor 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:
0for numeric types (byte,short,int,long,float,double)\u0000forcharfalseforbooleannullfor 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: 04. 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.
Common Interview Questions and Answers
Section titled “Common Interview Questions and Answers”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);}Real-World Use Cases
Section titled “Real-World Use Cases”- 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.