Back to Collectors
Q17Question 17 of 21

Collect employees into an array using toArray(Employee[]::new)

Key Concepts
  • toArray(Employee[]::new) collects a stream into a properly typed Employee[] array
  • The no-argument toArray() returns Object[], losing the element type
  • The constructor reference Employee[]::new is an IntFunction<Employee[]> that creates an array of the given size
  • Use toArray only when an API requires an array, for varargs, or for primitive stream arrays (int[], long[])
  • Default to collect(toList()) for most code because List is more flexible and composable
  • Primitive streams (IntStream, LongStream) have their own toArray() returning int[] or long[] directly

Definition

`toArray(Employee[]::new)` collects a stream into a typed `Employee[]` array, avoiding the untyped `Object[]` that the no-argument `toArray` returns.
  • toArray(IntFunction) takes an array generator that creates the array of the needed size.
  • Employee[]::new is an IntFunction supplying the type and size.
  • No-argument toArray() returns Object[], losing the element type.
  • Use case: when an API requires an array, for varargs, or for legacy interoperability.
  • Primitive streams have their own toArray() returning int[] or long[] directly.

At the National Bank of India, Priya empties the conveyor belt into a correctly-labelled box that holds exactly employees, not a generic box labelled 'Object'. The label matters because the next system expects an Employee box.

Understanding the Concepts

Why do you need the typed toArray?

The no-argument stream.toArray() returns an Object[], which loses the element type. Most APIs that accept arrays expect a specific type like Employee[]. The typed toArray(Employee[]::new) creates a properly typed array.

How do you use it?

JAVA
package com.bank.hr;

import java.math.BigDecimal;
import java.util.List;

public class ToArrayDemo {

    record Employee(String id, String name, BigDecimal salary) {}

    public static void main(String[] args) {
        List<Employee> staff = List.of(
            new Employee("SAV2001", "Rajesh",  new BigDecimal("1800000")),
            new Employee("SAV2002", "Priya",   new BigDecimal("1200000")),
            new Employee("SAV2003", "Meera",   new BigDecimal("1500000"))
        );

        // Typed array
        Employee[] array = staff.stream().toArray(Employee[]::new);
        System.out.println("Type: " + array.getClass().getSimpleName());
        System.out.println("Length: " + array.length);

        // Untyped array (Object[])
        Object[] objects = staff.stream().toArray();
        System.out.println("Untyped: " + objects.getClass().getSimpleName());
    }
}
TEXT
Type: Employee[]
Length: 3
Untyped: Object[]

How does the generator function work?

Employee[]::new is equivalent to size -> new Employee[size]. The stream calls this function with the required array length and fills the returned array with elements.

JAVA
// These are equivalent:
Employee[] a = staff.stream().toArray(Employee[]::new);
Employee[] b = staff.stream().toArray(size -> new Employee[size]);

When should you use toArray vs toList?

| Aspect | toArray(T[]::new) | collect(toList()) |
|---|---|---|
| Result type | Fixed-size array T[] | Flexible List |
| Generics | Limited (arrays and generics mix poorly) | Full support |
| Modification | Fixed size, elements replaceable | Resizable (ArrayList) |
| Use when | API requires array, varargs, primitives | Most application code |

What about primitive streams?

JAVA
// IntStream.toArray() returns int[] directly, no boxing
int[] salaries = java.util.stream.IntStream.of(50000, 60000, 70000).toArray();
// Returns int[], not Integer[]

// LongStream.toArray() returns long[]
long[] ids = java.util.stream.LongStream.rangeClosed(1, 100).toArray();

What are common mistakes?

Mistake: Using the no-argument toArray() and trying to cast.

JAVA
// WRONG: ClassCastException
Employee[] wrong = (Employee[]) staff.stream().toArray();
// Object[] cannot be cast to Employee[]

// CORRECT: use the typed generator
Employee[] correct = staff.stream().toArray(Employee[]::new);

What should a senior engineer know?

Default to List for flexibility and reserve toArray for specific needs: primitive performance via primitive-stream toArray, API/varargs interoperability, and fixed-size contracts. Converting a list to an array later is trivial with list.toArray(Employee[]::new) if needed.

What are common interview follow-up questions?

  • "Why not use the no-argument toArray?" It returns Object[], losing the element type.
  • "When should you use toArray?" When an API requires an array, for varargs, or for primitives.
  • "How do you get int[] from a stream?" Use IntStream.toArray(), not Stream.toArray().

Visual Overview

DIAGRAM
  staff.stream().toArray(Employee[]::new)
       │
       │  stream determines size = 3
       │  calls Employee[]::new with size 3
       ▼
  ┌──────────────────────────────────┐
  │  new Employee[3]                 │
  │  [0] = Rajesh                    │
  │  [1] = Priya                     │
  │  [2] = Meera                     │
  └──────────────────────────────────┘
  Result: Employee[] (typed, not Object[])

Key Takeaway

To collect a stream into a typed array, use toArray(Employee[]::new). The constructor reference is an IntFunction that the stream calls with the required length to allocate a properly typed Employee[] array. Without it, the no-argument toArray() returns an Object[] that loses the element type and forces unsafe casting.

At the National Bank of India, Rajesh uses toArray only when a legacy reporting API requires an Employee[]. For most code, he defaults to collect(toList()) because a List is more flexible, supports generics cleanly, and integrates with the Collections framework.

For primitive values, the primitive stream's toArray() returns int[] or long[] directly without boxing or a generator. Converting a list to an array later is trivial with list.toArray(T[]::new), so starting with a list and converting only when needed is the practical default.

Remember one sentence: toArray(T[]::new) gives a typed array; default to toList() for flexibility and use toArray only when an API specifically requires an array.

---

Share
Use ← → arrow keys to navigate