Skip to main content
Arrays Utility API

equals(), toString() & Streams

Arrays.equals(a, b) — element-wise comparison (use Arrays.deepEquals for 2D). Arrays.toString(arr) prints '[1, 2, 3]'. Arrays.deepToString for nested arrays. Arrays.stream(arr) enables sum(), max(), filter(), distinct(), and collect().

O(n) to O(n log n) depending on op
·
O(1) to O(n)

How It Works

Arrays.equals(a, b) compares two arrays element by element — unlike ==, which only tests reference identity, or a.equals(b), which arrays inherit unchanged from Object. Nested arrays need Arrays.deepEquals, which recurses into sub-arrays. The same split applies to printing: Arrays.toString(arr) renders '[1, 2, 3]' while Arrays.deepToString handles 2D arrays, and printing an array directly yields a useless hash-like identifier.

Arrays.stream(arr) opens the functional toolbox on primitives: sum(), max(), min(), average() as terminal operations, and filter, map, distinct, sorted as intermediate ones. These are O(n) conveniences, not asymptotic wins — their value is expressing frequency counts, aggregates, and transformations in a line rather than a loop.

Step-by-Step Visualization

Arrays.equals vs Arrays.deepEquals — use deep for 2D/nested arrays
1
0
2
1
3
2
4
3
5
4
equals([1,2,3],[1,2,3])true ✓
equals(m1, m2)false ⚠ (refs)
deepEquals(m1, m2)true ✓
1/4

Code

Java
int[]   a  = {1, 2, 3};
int[][] m1 = {{1, 2}, {3, 4}};
int[][] m2 = {{1, 2}, {3, 4}};

// ─── Comparison ───────────────────────────────────────────────
Arrays.equals(a, b);         // true  — element-wise (1D)
Arrays.equals(m1, m2);       // false — compares row references!
Arrays.deepEquals(m1, m2);   // true  — recursive element-wise (2D+)

// ─── Print ────────────────────────────────────────────────────
Arrays.toString(a);          // "[1, 2, 3]"
Arrays.deepToString(m1);     // "[[1, 2], [3, 4]]"

// ─── Streams (IntStream — no boxing) ─────────────────────────
Arrays.stream(a).sum();                      // 6
Arrays.stream(a).max().getAsInt();           // 3
Arrays.stream(a).min().getAsInt();           // 1
Arrays.stream(a).filter(x -> x > 1).count(); // 2
Arrays.stream(a).distinct().toArray();        // dedup

// ─── Useful one-liners ────────────────────────────────────────
// int[] → String[]
String[] strs = Arrays.stream(a).mapToObj(Integer::toString).toArray(String[]::new);

// prefix sum in-place
int[] pre = new int[a.length + 1];
Arrays.setAll(pre, i -> i == 0 ? 0 : pre[i - 1] + a[i - 1]);

Tips & Gotchas

1Arrays.equals(a, b) — use for primitives; Objects.deepEquals for objects
2Arrays.deepEquals / Arrays.deepToString handle multi-dimensional arrays
3Arrays.stream() returns IntStream/LongStream for primitives — no boxing
4IntStream has sum(), min(), max(), average(), distinct() built in

Practice Problems

  • 1Running Sum of 1d Array
  • 2Richest Customer Wealth
  • 3Valid Anagram
  • 4Maximum Subarray

About the Arrays Utility API Pattern

java.util.Arrays methods and array ↔ collection conversion patterns. These utilities handle sorting, searching, copying, filling, and bridging between primitive arrays and Java collections.

Key insight

When you see 'subarray', 'contiguous', or 'in-place', think arrays. The key is reducing brute-force O(n²) to O(n) using sliding window, two pointers, or prefix sums.

Common Array Interview Problems

  • Two Sum
  • Best Time to Buy & Sell Stock
  • Maximum Subarray
  • Merge Intervals
  • Product of Array Except Self
  • Container With Most Water

Frequently Asked Questions

Why does array1 == array2 return false even when contents match?

The == operator compares references, asking whether both variables point to the same object in memory. Content comparison requires Arrays.equals for one-dimensional arrays or Arrays.deepEquals for nested ones; arrays never override Object.equals, so a.equals(b) is just == in disguise.

When should I use streams versus a plain loop on arrays in interviews?

Streams shine for quick aggregates — Arrays.stream(nums).sum() or .max().getAsInt() — and keep setup code short. Inside hot loops or when the interviewer probes performance, a plain for-loop avoids boxing and lambda overhead and is easier to reason about step by step.

How do I print a 2D array for debugging?

Use Arrays.deepToString(matrix), which recursively formats nested arrays into readable brackets. Arrays.toString on a 2D array prints the hash-like identity of each row rather than its contents, which is a common source of confusing debug output.