Arrays & Multidimensional Arrays
15 questions found
How would you implement a memory-efficient sparse matrix representation in Java when a large 2D array would mostly contain zero/default values, avoiding the memory waste of a full dense array?
Advanced
A sparse matrix stores only the non-default (non-zero) elements, commonly using a Map<Long, T> keyed by an encoded (row, column) pair, or a Map<Integer, Map<Integer, T>> for nested row-then-column lookup, or specialized formats like Compressed Sparse Row (CSR) for numerical computing -- this avoids allocating and holding memory for the potentially enormous number of default-valued cells a genuinely sparse dataset (like a large graph's adjacency matrix, or a mostly-empty spreadsheet) would otherwise require if represented as a dense 2D array.
public class SparseMatrix {
private final Map<Long, Double> data = new HashMap<>();
private final int cols;
public SparseMatrix(int cols) { this.cols = cols; }
private long key(int row, int col) { return (long) row * cols + col; }
public void set(int row, int col, double value) {
if (value == 0.0) data.remove(key(row, col));
else data.put(key(row, col), value);
}
public double get(int row, int col) {
return data.getOrDefault(key(row, col), 0.0);
}
}
Real-world example
A recommendation engine's user-item interaction matrix (millions of users by millions of items, but each user has only interacted with a tiny fraction) is stored as a sparse Map-based structure rather than a dense 2D array, since a dense representation at that scale would require far more memory than any reasonable server could provide.
Common follow-ups: What's the performance trade-off of Map-based sparse storage versus a dense array for operations like matrix multiplication?;How do specialized sparse matrix libraries (like those used in scientific computing) further optimize beyond a simple HashMap-based approach?
Collections Framework;Diagnostics & Performance
What is array covariance's relationship to generic arrays, and why can't you directly create a generic array like new T[10] or new List<String>[10]?
Intermediate
Due to Java's type erasure, generic type information isn't available at runtime, so the JVM couldn't correctly enforce the component type of a genuinely generic array at the point of array creation -- combined with array covariance's already-demonstrated unsoundness (ArrayStoreException), allowing new T[] or new List<String>[] directly would create even more severe, undetectable type-safety holes, so Java simply disallows this syntax entirely at compile time, requiring workarounds like creating an Object[] and unsafely casting, or preferring a generic-friendly collection like ArrayList<T> instead.
public class Container<T> {
// private T[] items = new T[10]; // COMPILE ERROR: generic array creation
@SuppressWarnings("unchecked")
private T[] items = (T[]) new Object[10]; // common workaround, but unsafe and generates a warning
// Preferred alternative: just use a List instead
private List<T> betterItems = new ArrayList<>();
}
Real-world example
A generic container class initially attempts private T[] items = new T[10] and hits a compile error, leading the team to either use the unsafe Object[]-cast workaround (accepting the unchecked warning) or, preferably, refactor to use ArrayList<T> internally instead, sidestepping the entire generic array limitation.
Common follow-ups: Why does the unsafe (T[]) cast workaround still risk a ClassCastException later, and under what circumstances?;How does the JDK's own source code (like ArrayList's internal implementation) handle this exact limitation internally?
Generics;Collections Framework
How do you declare and initialize an array of objects (reference types) versus an array of primitives, and what is the key difference in their default values?
Beginner
An array of primitives (int[], double[]) has elements automatically initialized to their type's zero-equivalent default (0, 0.0, false), while an array of reference types (String[], custom objects) has every element initialized to null by default, since no object instance is automatically created -- attempting to call a method on an uninitialized reference-type array element before explicitly assigning it throws a NullPointerException.
int[] nums = new int[3]; // {0, 0, 0}
boolean[] flags = new boolean[3]; // {false, false, false}
String[] names = new String[3]; // {null, null, null}
System.out.println(names[0].length()); // throws NullPointerException, since names[0] is null
Real-world example
A beginner's attempt to call .length() on an element of a freshly created String[] array (without first assigning actual String values to each slot) throws a NullPointerException, a common early mistake stemming from not realizing reference-type arrays default to null rather than empty strings.
Common follow-ups: Why don't reference-type arrays default to an empty object instance instead of null?;How would you safely initialize every element of an object array to a non-null default value?
Java Fundamentals: Syntax
Data Types & Operators;Exceptions
How would you flatten a 2D array into a 1D array, and conversely, reshape a 1D array into a 2D array?
Intermediate
Flattening a 2D array involves iterating each row and copying its elements sequentially into a pre-sized 1D destination array (tracking a running offset via System.arraycopy() for efficiency); reshaping a 1D array into 2D requires knowing the desired row/column dimensions in advance and copying corresponding slices of the source array into each newly allocated row -- neither operation has a single built-in JDK utility method, so both are typically implemented manually using System.arraycopy() for performance.
public static int[] flatten(int[][] matrix) {
int totalLength = Arrays.stream(matrix).mapToInt(row -> row.length).sum();
int[] result = new int[totalLength];
int offset = 0;
for (int[] row : matrix) {
System.arraycopy(row, 0, result, offset, row.length);
offset += row.length;
}
return result;
}
Real-world example
An image-processing routine flattens a 2D pixel grid into a single contiguous 1D array before passing it to a native image-encoding library expecting flat pixel data, using System.arraycopy() per row for efficient bulk copying rather than a slower element-by-element nested loop.
Common follow-ups: What is the time complexity of the flattening operation relative to the total number of elements?;How would you handle flattening a jagged (non-rectangular) 2D array where rows have different lengths?
Diagnostics & Performance;Collections Framework
How does the JVM lay out array objects in memory, including the array header overhead, and how does this affect memory efficiency for very large arrays of primitives versus boxed wrapper types?
Advanced
A Java array is itself an object on the heap, carrying an object header (typically 12-16 bytes on a 64-bit JVM, including a mark word and class pointer) plus a 4-byte length field, followed by the actual element data laid out contiguously -- a primitive array (like int[]) stores raw values directly and compactly in this contiguous block, while an array of boxed wrapper types (Integer[]) instead stores references (pointers) to separately-heap-allocated Integer objects, meaning each element incurs both the pointer's own 4-8 bytes AND a separate object header for each boxed Integer instance, resulting in dramatically higher memory usage and worse cache locality for large numeric datasets.
// Primitive array: compact, contiguous memory, ~16 bytes header + 4 bytes per int
int[] primitiveArray = new int[1_000_000]; // roughly 4MB total
// Boxed array: each element is a separate heap object plus a reference
Integer[] boxedArray = new Integer[1_000_000]; // roughly 20MB+ total (references + individual Integer objects)
Real-world example
A scientific computing application processing millions of numeric data points switches from using an Integer[] (or a generic List<Integer>) to a raw int[] array after profiling revealed the boxed representation was consuming roughly 4-5x more heap memory and causing significantly worse CPU cache performance due to pointer-chasing through scattered Integer objects.
Common follow-ups: How does the JIT compiler's escape analysis sometimes mitigate boxing overhead in tight loops?;What is the memory layout difference between a 2D primitive array and a flattened 1D equivalent?
Garbage Collection;Diagnostics & Performance