Java

Arrays, BitSet, and Primitives

Discover the performance foundations that power many Java collections. From the Arrays utility class with its essential methods to BitSet for memory-efficient boolean storage, understand when primitives outperform objects and how to leverage them effectively.

📋 At a Glance

AspectDetails
TopicArrays class, primitive arrays, BitSet, memory optimization
ComplexityIntermediate
PrerequisitesPart 1 (Framework Architecture)
Time to Master3-4 hours
Interview FrequencyHigh (Arrays.asList trap, primitive vs wrapper performance)

🎯 What You'll Learn

After completing this article, you will be able to:

  1. Understand Arrays.asList() gotchas and fixed-size list behavior
  2. Choose between primitive arrays and wrapper collections for performance
  3. Use BitSet for memory-efficient flag storage
  4. Leverage parallel array operations effectively
  5. Avoid common boxing/unboxing performance traps

Production Story: The Fixed-Size List Disaster

The Incident

Our recommendation engine was working perfectly in development. Then it hit production and started throwing UnsupportedOperationException left and right.

The error logs pointed to what seemed like innocent code:

JAVA(15 lines)
Code
Loading syntax highlighter...

Why Arrays.asList() Isn't What You Think

Arrays.asList() doesn't return a regular ArrayList. It returns java.util.Arrays$ArrayList - a fixed-size list backed by the original array.
JAVA(10 lines)
Code
Loading syntax highlighter...

Let me show you the actual implementation:

JAVA(25 lines)
Code
Loading syntax highlighter...

The Traps

JAVA(21 lines)
Code
Loading syntax highlighter...

The Fix

JAVA(17 lines)
Code
Loading syntax highlighter...

Impact and Lessons

Impact:
  • 2,847 failed recommendation requests in 15 minutes
  • Users saw empty recommendation panels
  • SEO impact from error responses
Lessons Learned:
  1. Arrays.asList() returns a fixed-size view, not a copy
  2. Always wrap in new ArrayList<>() if you need mutability
  3. Unit tests should cover add/remove operations
  4. Consider List.of() when immutability is acceptable

Mental Model: Arrays as Building Blocks

Think of arrays as the concrete foundation of a building:

TEXT(37 lines)
Code
Loading syntax highlighter...

BitSet as Compact Boolean Storage

TEXT(10 lines)
Code
Loading syntax highlighter...

Deep Dive: Arrays Utility Class

Arrays.asList() - The View Pattern

JAVA(15 lines)
Code
Loading syntax highlighter...

Arrays.copyOf() and copyOfRange()

JAVA(14 lines)
Code
Loading syntax highlighter...

Arrays.fill() and setAll()

JAVA(14 lines)
Code
Loading syntax highlighter...

Arrays.sort() vs parallelSort()

JAVA(17 lines)
Code
Loading syntax highlighter...

Arrays.binarySearch()

JAVA(12 lines)
Code
Loading syntax highlighter...

Arrays.mismatch() and compare() (Java 9+)

JAVA(17 lines)
Code
Loading syntax highlighter...

Deep Dive: Primitive Arrays vs Wrapper Collections

Memory Comparison

JAVA(20 lines)
Code
Loading syntax highlighter...

Performance Comparison

JAVA(36 lines)
Code
Loading syntax highlighter...

Boxing/Unboxing Traps

JAVA(29 lines)
Code
Loading syntax highlighter...

When to Use What

TEXT(13 lines)
Code
Loading syntax highlighter...

Deep Dive: BitSet

BitSet Basics

JAVA(19 lines)
Code
Loading syntax highlighter...

BitSet Memory Efficiency

JAVA(16 lines)
Code
Loading syntax highlighter...

BitSet Operations

JAVA(34 lines)
Code
Loading syntax highlighter...

BitSet Iteration

JAVA(21 lines)
Code
Loading syntax highlighter...

BitSet Use Cases

JAVA(51 lines)
Code
Loading syntax highlighter...

Deep Dive: Parallel Array Operations

When Parallel Helps

JAVA(14 lines)
Code
Loading syntax highlighter...

parallelPrefix() - Cumulative Operations

JAVA(18 lines)
Code
Loading syntax highlighter...

Parallel Stream from Arrays

JAVA(18 lines)
Code
Loading syntax highlighter...

⚠️ Common Mistakes

Mistake 1: Modifying Arrays.asList() Result

JAVA(11 lines)
Code
Loading syntax highlighter...

Mistake 2: Arrays.asList() with Primitives

JAVA(14 lines)
Code
Loading syntax highlighter...

Mistake 3: Forgetting to Sort Before binarySearch

JAVA(9 lines)
Code
Loading syntax highlighter...

Mistake 4: Integer Comparison with ==

JAVA(12 lines)
Code
Loading syntax highlighter...

Mistake 5: BitSet Size Confusion

JAVA(13 lines)
Code
Loading syntax highlighter...

🐛 Debug This

Challenge 1: The Disappearing Elements

JAVA(10 lines)
Code
Loading syntax highlighter...
✅ Answer:
Both print: X, Y, C

The list is backed by the array, so:

  • list.set(0, "X") changes array[0] to "X"
  • array[1] = "Y" changes list.get(1) to "Y"

Both the list and array reflect all changes.

Challenge 2: The Unexpected Size

JAVA(7 lines)
Code
Loading syntax highlighter...
✅ Answer:
Output: 1, 5
  • ints is an int[] (primitive array). Arrays.asList(ints) treats it as a single object, creating List<int[]> with size 1.
  • objects is an Object[]. Arrays.asList(objects) creates List<Object> with 5 elements.

Challenge 3: The BitSet Mystery

JAVA(11 lines)
Code
Loading syntax highlighter...
✅ Answer:

Output:

TEXT(2 lines)
Code
Loading syntax highlighter...

XOR sets bits that are in one set but not both:

  • Bit 1: in a only → set
  • Bit 2: in b only → set
  • Bit 3: in both → cleared

💻 Exercises

Exercise 1: Safe ArrayList Creation

Write a utility method that creates a mutable ArrayList from varargs, handling both objects and primitives:
JAVA(4 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(19 lines)
Code
Loading syntax highlighter...

Exercise 2: BitSet-based Set Operations

Implement a class that uses BitSet for efficient set operations on integers in a known range:

JAVA(10 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(49 lines)
Code
Loading syntax highlighter...

Exercise 3: Parallel Array Processor

Create a utility for parallel array processing with configurable threshold:

JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(33 lines)
Code
Loading syntax highlighter...

Exercise 4: Array Rotation

Implement efficient in-place array rotation:

JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(25 lines)
Code
Loading syntax highlighter...

Exercise 5: Find Missing Numbers

Use BitSet to find missing numbers in a sequence:

JAVA(4 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(28 lines)
Code
Loading syntax highlighter...

🎤 Senior-Level Interview Questions

Question 1: Arrays.asList() Behavior

Q: What's the difference between Arrays.asList() and List.of()? When would you use each?
A:
AspectArrays.asList()List.of() (Java 9+)
MutabilityFixed-size (can set, can't add/remove)Fully immutable
Null elementsAllowedNot allowed
Array backingYes (changes reflect)No (defensive copy)
MemoryShares with source arrayOwn memory
JAVA(8 lines)
Code
Loading syntax highlighter...

Question 2: Primitive vs Wrapper Performance

Q: Why is int[] significantly faster than ArrayList<Integer> for numerical operations?
A: Three main reasons:
  1. No boxing/unboxing: int[] stores raw 4-byte values. ArrayList<Integer> requires creating Integer objects (boxing) and extracting int values (unboxing).
  2. Memory layout: int[] is contiguous in memory (cache-friendly). ArrayList<Integer> stores references to Integer objects scattered in heap.
  3. Memory overhead: int[] uses 4 bytes per element. Integer uses ~20 bytes per element (16-byte object header + 4-byte int + reference).
JAVA(2 lines)
Code
Loading syntax highlighter...

Question 3: BitSet Internals

Q: How does BitSet store data internally, and what are its space advantages?
A:
BitSet uses a long[] array internally, where each long stores 64 bits:
JAVA(14 lines)
Code
Loading syntax highlighter...

Space comparison for 10,000 flags:

  • boolean[]: 10,000 bytes
  • HashSet<Integer> (50% set): ~200,000 bytes
  • BitSet: ~1,280 bytes (10,000/64 * 8)

BitSet is 8x better than boolean[] and ~150x better than HashSet.

Question 4: parallelSort() vs sort()

Q: When should you use Arrays.parallelSort() instead of Arrays.sort()?
A:
Use parallelSort() when:
  • Array has more than ~8,192 elements (JDK threshold)
  • Operation is CPU-bound (no I/O waiting)
  • Multiple CPU cores are available
  • Elements are independent (no shared state)

Don't use when:

  • Small arrays (parallel overhead > benefit)
  • Already in a parallel context (thread pool saturation)
  • Deterministic ordering needed (parallelSort is stable but may vary)
JAVA(6 lines)
Code
Loading syntax highlighter...

Question 5: Array Copy Methods

Q: What's the difference between System.arraycopy(), Arrays.copyOf(), and clone()?
A:
JAVA(22 lines)
Code
Loading syntax highlighter...

Question 6: Integer Cache

Q: Explain the Integer cache and its implications for == comparison.
A:
Java caches Integer objects for values -128 to 127 (configurable via -XX:AutoBoxCacheMax):
JAVA(20 lines)
Code
Loading syntax highlighter...

📝 Summary & Key Takeaways

Arrays.asList() Essentials

  • Returns fixed-size list backed by array
  • Cannot add/remove, but can set elements
  • Changes bidirectionally reflect in array and list
  • Doesn't work as expected with primitive arrays

Primitive vs Wrapper Performance

  • int[] uses 6x less memory than ArrayList<Integer>
  • Avoid boxing/unboxing in hot loops
  • Use primitive streams (IntStream, LongStream, DoubleStream)
  • Integer cache: -128 to 127 are cached, use .equals() for comparison

BitSet Benefits

  • 8x more memory-efficient than boolean[]
  • Efficient set operations (and, or, xor)
  • Use for flags, Bloom filters, sieves
  • cardinality() for count, stream() for iteration

Parallel Operations

  • Use parallelSort() for arrays > 8,192 elements
  • parallelSetAll() for expensive computations
  • parallelPrefix() for cumulative operations
  • Not always faster - measure before using

🏁 Conclusion

Arrays and BitSet are the unsung heroes of Java collections. While ArrayList and HashMap get all the attention, understanding these foundational types helps you:

  1. Avoid common traps like the Arrays.asList() fixed-size gotcha
  2. Optimize memory using primitive arrays and BitSet where appropriate
  3. Improve performance with parallel array operations
  4. Make informed choices between primitives and wrappers

Key takeaways:

  • Arrays.asList() returns a view, not a copy - wrap in new ArrayList<>() for mutability
  • Primitive arrays are 6x more memory-efficient than wrapper collections
  • BitSet is perfect for boolean flags and set operations on integers
  • Parallel operations help for large arrays (>8,192 elements)

In the next article, we'll dive into ArrayList's internals - seeing how it uses these array primitives to provide a dynamic, growable collection.


📅 Review Schedule

To solidify your understanding, review this material:

  • Tomorrow: Re-read the Arrays.asList() traps section
  • In 3 days: Implement Exercise 2 (BitSet-based Set) again
  • In 1 week: Explain primitive vs wrapper performance to a colleague
  • In 2 weeks: Review the production story and common mistakes