Why sometimes .stream() and sometimes Stream.of(...)?
Use data.stream() when the object implements Collection, such as
List, Set, or Queue. Use utility methods when the
value itself does not have a stream method.
// Collection owns stream()
employees.stream()
// Array does not have stream()
Arrays.stream(numbers)
// Individual values become a stream
Stream.of("IT", "HR", "Finance")
// One nullable object becomes 0 or 1 stream item
Stream.ofNullable(employee)
List / ArrayList / LinkedList
All lists implement Collection, so use .stream().
List<Employee> employees = new ArrayList<>();
List<String> names = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
Set / HashSet / TreeSet
Sets also implement Collection. Stream order depends on the set type.
Set<String> departments = Set.of("IT", "HR", "Finance");
departments.stream()
.filter(d -> d.length() > 2)
.forEach(System.out::println);
Queue / Deque
Queues are collections too. Use stream when you want processing without removing items.
Queue<Integer> queue = new ArrayDeque<>();
int total = queue.stream()
.mapToInt(Integer::intValue)
.sum();
Object Array
Arrays do not have .stream(). Use Arrays.stream(array).
Employee[] employeeArray = {
new Employee(101, "John", "IT", 70000)
};
Arrays.stream(employeeArray)
.map(Employee::getName)
.forEach(System.out::println);
Primitive Arrays
Primitive arrays become primitive streams: IntStream, LongStream, or DoubleStream.
int[] salaries = {70000, 50000, 90000};
int max = Arrays.stream(salaries)
.max()
.orElse(0);
Varargs / Fixed Values
Use Stream.of(...) when values are listed directly.
Stream.of("John", "Alice", "Bob")
.map(String::toUpperCase)
.forEach(System.out::println);
HashMap / LinkedHashMap
A map is not a collection of values directly. Stream entries, keys, or values.
Map<String, Integer> deptCount = new HashMap<>();
deptCount.entrySet().stream()
.filter(e -> e.getValue() > 1)
.forEach(System.out::println);
Map Keys / Values
Use keySet() for keys and values() for values.
map.keySet().stream()
.forEach(System.out::println);
map.values().stream()
.forEach(System.out::println);
String Characters
chars() creates an IntStream of character codes.
String name = "Stream";
name.chars()
.mapToObj(c -> (char) c)
.forEach(System.out::println);
String Words
Split the string, then stream the array.
String sentence = "Java stream api practice";
Arrays.stream(sentence.split("\\s+"))
.filter(word -> word.length() > 4)
.forEach(System.out::println);
Single Object
Use Stream.of(object) for one non-null object.
Employee employee = new Employee(101, "John", "IT", 70000);
Stream.of(employee)
.map(Employee::getName)
.forEach(System.out::println);
Nullable Object
Use Stream.ofNullable(...) so null becomes an empty stream.
Employee employee = findEmployee();
Stream.ofNullable(employee)
.map(Employee::getName)
.forEach(System.out::println);
Optional
Java 9+ has optional.stream(), useful for flattening optionals.
Optional<Employee> optional = findById(101);
optional.stream()
.map(Employee::getDepartment)
.forEach(System.out::println);
Nested List
Use flatMap to convert nested streams into one stream.
List<List<String>> skills = List.of(
List.of("Java", "SQL"),
List.of("Spring", "Java")
);
List<String> flat = skills.stream()
.flatMap(List::stream)
.distinct()
.collect(Collectors.toList());
File Lines
Use Files.lines(path). Close it with try-with-resources.
Path path = Paths.get("employees.txt");
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> line.contains("IT"))
.forEach(System.out::println);
}
Iterator / Iterable
Use StreamSupport.stream(...) when an object is iterable but not a collection.
Iterable<Employee> iterable = getEmployees();
Stream<Employee> stream = StreamSupport.stream(
iterable.spliterator(),
false
);
Generate / Iterate
Create streams without existing data using generate or iterate.
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);
IntStream.iterate(1, n -> n + 1)
.limit(10)
.forEach(System.out::println);
Primitive Ranges
Use range streams when you need indexes or numbers.
IntStream.range(0, employees.size())
.mapToObj(i -> (i + 1) + ". " + employees.get(i).getName())
.forEach(System.out::println);