How Stream API Can Shrink Your Java Code from 24 Lines to 5
This article explains Java 8's Stream API, showing how to replace verbose pre‑Java‑8 collection processing with concise, declarative stream operations, covering stream creation, intermediate and terminal operations, and practical examples such as filtering, sorting, mapping, grouping, and aggregation.
What is Stream API?
Java 8 introduced Lambda expressions and the Stream API; combined, they allow declarative processing of collections, making code shorter and more readable.
Example: Filter, sort, and extract dish names
Given a list of Dish objects, the requirement is to select dishes with fewer than 400 calories, sort them, and collect their names.
Pre‑Java‑8 implementation
private List<String> beforeJava7(List<Dish> dishList) {
List<Dish> lowCaloricDishes = new ArrayList<>();
// 1. filter calories < 400
for (Dish dish : dishList) {
if (dish.getCalories() < 400) {
lowCaloricDishes.add(dish);
}
}
// 2. sort by calories
Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
@Override
public int compare(Dish o1, Dish o2) {
return Integer.compare(o1.getCalories(), o2.getCalories());
}
});
// 3. extract names
List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish d : lowCaloricDishes) {
lowCaloricDishesName.add(d.getName());
}
return lowCaloricDishesName;
}Java 8 implementation with Stream API
private List<String> afterJava8(List<Dish> dishList) {
return dishList.stream()
.filter(d -> d.getCalories() < 400) // filter
.sorted(comparing(Dish::getCalories)) // sort
.map(Dish::getName) // extract name
.collect(Collectors.toList()); // collect
}The same logic shrinks from 24 lines to 5.
New requirement: Group dishes by type
Pre‑Java‑8 implementation
private static Map<Type, List<Dish>> beforeJdk8(List<Dish> dishList) {
Map<Type, List<Dish>> result = new HashMap<>();
for (Dish dish : dishList) {
if (result.get(dish.getType()) == null) {
List<Dish> dishes = new ArrayList<>();
dishes.add(dish);
result.put(dish.getType(), dishes);
} else {
result.get(dish.getType()).add(dish);
}
}
return result;
}Java 8 implementation with Stream API
private static Map<Type, List<Dish>> afterJdk8(List<Dish> dishList) {
return dishList.stream().collect(groupingBy(Dish::getType));
}How to create streams
From a collection: list.stream() From an array: Arrays.stream(array) From values: Stream.of(...) From a file: Files.lines(Paths.get("data.txt")) From functions: Stream.iterate(seed, f).limit(n) or
Stream.generate(supplier).limit(n)Intermediate operations (lazy)
filter: keep elements that match a predicate. distinct: remove duplicates. limit: truncate the stream to a maximum size. skip: discard the first n elements. map: transform each element. flatMap: flatten a stream of streams. allMatch, anyMatch, noneMatch: element‑matching predicates.
Terminal operations (trigger execution)
count: number of elements. findFirst / findAny: retrieve an element. reduce: combine elements (e.g., sum). min / max: smallest / largest element. sum, averagingInt, summarizingInt: numeric aggregations. forEach: perform an action on each element. collect with toList, toSet, joining, groupingBy, partitioningBy: gather results into collections or maps.
Conclusion
Using the Stream API dramatically simplifies collection processing, improves readability, and reduces boilerplate code. Adopt streams for declarative data handling, but avoid mixing imperative and declarative styles in the same pipeline.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
