
The Java 8 Stream API is a powerful tool in Java programming. It facilitates the processing of collections of objects in a functional and declarative manner. Its primary purpose is to provide developers with a streamlined way to perform complex operations on collections, such as filtering, mapping, and reducing elements.
Benefits of Using Java Stream API:
- Conciseness: Java Stream API allows you to write more concise and expressive code. Compared to traditional looping constructs, it improves readability and maintainability.
- Functional Programming Paradigm: Leveraging functional programming concepts, Java Stream API enables developers to write declaratively, focusing on what needs to be done rather than how it should be done.
- Parallel Processing: The API supports parallel processing, efficiently utilizing multi-core processors and improving performance for large datasets.
- Intermediate and Terminal Operations: Java Stream API provides a wide range of intermediate and terminal operations. We can mention map, filter, collect, reduce, and forEach, enabling developers to perform complex transformations and aggregations effortlessly.
Java Stream API Usage Examples
The exercise will start with an actor record class. An actor has first and last name, gender, movie appearance, and age. Based on this record class, let´s create a list with 13 actors, having one of them (Penelope Guiness) added twice. In the end, the list will contain 14 entries and this repetition will be explored throughout the examples.
Actor´s Record Class
public record Actor(String firstName, String lastName, String gender, String movie, int age) {}
List of Actors – With Repetition
private static Collection<Actor> getAllActors() {
return Arrays.asList(
new Actor("Penelope", "Guiness" , "F", "Angels Life" , 30),
new Actor("Penelope", "Guiness" , "F", "Angels Life" , 30),
new Actor("Marta" , "Guiness" , "F", "Bulworth Commandments" , 30),
new Actor("Cuba" , "Olivier" , "M", "Angels Life" , 42),
new Actor("Nick" , "Wahlberg" , "M", "Dracula Crystal" , 50),
new Actor("Jennifer", "Davis" , "F", "Angels Life" , 28),
new Actor("Ed" , "Chase" , "M", "Young Language" , 10),
new Actor("Bette" , "Nicholson" , "F", "Crossroads Casualties" , 87),
new Actor("Johnny" , "Lollobrigida", "M", "Pacific Amistad" , 35),
new Actor("Matthew" , "Johansson" , "M", "Conquerer Nuts" , 72),
new Actor("Grace" , "Mostel" , "F", "Angels Life" , 63),
new Actor("Uma" , "Wood" , "F", "Clash Freddy" , 20),
new Actor("Joe" , "Swank" , "M", "Waterfront Deliverance", 20),
new Actor("Penelope", "Bergen" , "F", "Hills Neighbors" , 55));
}
Removing Repeated Actors – Stream#distintct()
private static Collection<Actor> getDistinctActors() {
return getAllActors().stream()
.distinct()
.collect(Collectors.toList());
}
Counting All Actors – Stream#count()
private static long countActors() {
return getAllActors().stream()
.count();
}
count : 14
Counting Distinct Actors – Stream#distinct()#count()
private static long countDistinctActors() {
return getDistinctActors().stream()
.count();
}
count + distinct : 13
Getting the Oldest Actor – Stream#max(Comparator#comparingInt())
private static Optional<Actor> getOldestActor() {
return getAllActors().stream()
.max(Comparator.comparingInt(Actor::age));
}
max (AGE) : Optional[Actor[firstName=Bette, lastName=Nicholson, gender=F, movie=Crossroads Casualties, age=87]]
Getting the Youngest Actor – Stream#min(Comparator#comparingInt())
private static Optional<Actor> getYoungestActor() {
return getAllActors().stream()
.min(Comparator.comparingInt(Actor::age));
}
min (AGE) : Optional[Actor[firstName=Ed, lastName=Chase, gender=M, movie=Young Language, age=10]]
Getting the Average Age of All Actors – Stream#collect(Comparator#averagingInt())
private static double getAverageAgeOfAllActors() {
return getAllActors().stream()
.collect(Collectors.averagingInt(Actor::age));
}
average (AGE) : 40.857142857142854
Getting the Average Age of Distinct Actors – Stream#distinct()#collect(Comparator#averagingInt())
private static double getAverageAgeOfDistinctActors() {
return getAllActors().stream()
.distinct()
.collect(Collectors.averagingInt(Actor::age));
}
average (AGE) + distinct: 41.69230769230769
Filtering Actors By First Name Starting With ‘J’ – Stream#filter()
private static Collection<Actor> filterActorsByFirstNameStartingWith(String prefix) {
return getAllActors().stream()
.filter(actor -> actor.firstName().startsWith(prefix))
.collect(Collectors.toList());
}
filter (J) + forEach :
- Actor[firstName=Jennifer, lastName=Davis, gender=F, movie=Angels Life, age=28]
- Actor[firstName=Johnny, lastName=Lollobrigida, gender=M, movie=Pacific Amistad, age=35]
- Actor[firstName=Joe, lastName=Swank, gender=M, movie=Waterfront Deliverance, age=20]
Limiting to the First ‘3’ Results – Stream#limit()
private static Collection<Actor> getActorsSortedByFirstNameAscAndLastNameAscLimitedBy(
int maxSize) {
return getActorsSortedByFirstNameAscAndLastNameAsc().stream()
.limit(maxSize)
.collect(Collectors.toList());
}
sorted + limit (3) :
- Actor[firstName=Bette, lastName=Nicholson, gender=F, movie=Crossroads Casualties, age=87]
- Actor[firstName=Cuba, lastName=Olivier, gender=M, movie=Angels Life, age=42]
- Actor[firstName=Ed, lastName=Chase, gender=M, movie=Young Language, age=10]
Skipping the First ‘9’ Results – Stream#skip()
private static Collection<Actor> getActorsSortedByFirstNameAscAndLastNameAscSkipingFirst(int n) {
return getActorsSortedByFirstNameAscAndLastNameAsc().stream()
.skip(n)
.collect(Collectors.toList());
}
sorted + skip (9) :
- Actor[firstName=Nick, lastName=Wahlberg, gender=M, movie=Dracula Crystal, age=50]
- Actor[firstName=Penelope, lastName=Bergen, gender=F, movie=Hills Neighbors, age=55]
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Uma, lastName=Wood, gender=F, movie=Clash Freddy, age=20]
Sorting Actors By First and Last Name Ascending – Stream#sorted(Comparator#comparing() #thenComparing())
private static Collection<Actor> getActorsSortedByFirstNameAscAndLastNameAsc() {
return getAllActors().stream()
.sorted(Comparator.comparing(Actor::firstName)
.thenComparing(Actor::lastName))
.collect(Collectors.toList());
}
sorted (first+last name):
- Actor[firstName=Bette, lastName=Nicholson, gender=F, movie=Crossroads Casualties, age=87]
- Actor[firstName=Cuba, lastName=Olivier, gender=M, movie=Angels Life, age=42]
- Actor[firstName=Ed, lastName=Chase, gender=M, movie=Young Language, age=10]
- Actor[firstName=Grace, lastName=Mostel, gender=F, movie=Angels Life, age=63]
- Actor[firstName=Jennifer, lastName=Davis, gender=F, movie=Angels Life, age=28]
- Actor[firstName=Joe, lastName=Swank, gender=M, movie=Waterfront Deliverance, age=20]
- Actor[firstName=Johnny, lastName=Lollobrigida, gender=M, movie=Pacific Amistad, age=35]
- Actor[firstName=Marta, lastName=Guiness, gender=F, movie=Bulworth Commandments, age=30]
- Actor[firstName=Matthew, lastName=Johansson, gender=M, movie=Conquerer Nuts, age=72]
- Actor[firstName=Nick, lastName=Wahlberg, gender=M, movie=Dracula Crystal, age=50]
- Actor[firstName=Penelope, lastName=Bergen, gender=F, movie=Hills Neighbors, age=55]
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Uma, lastName=Wood, gender=F, movie=Clash Freddy, age=20]
Filtering Actors With Age Greater Than ’50’ – Stream#filter()
private static Collection<Actor> getActorsWithAgeGreaterThan(int age) {
return getDistinctActors().stream()
.filter(actor -> actor.age() > age)
.collect(Collectors.toList());
}
filter (> 50) :
- Actor[firstName=Bette, lastName=Nicholson, gender=F, movie=Crossroads Casualties, age=87]
- Actor[firstName=Matthew, lastName=Johansson, gender=M, movie=Conquerer Nuts, age=72]
- Actor[firstName=Grace, lastName=Mostel, gender=F, movie=Angels Life, age=63]
- Actor[firstName=Penelope, lastName=Bergen, gender=F, movie=Hills Neighbors, age=55]
Grouping Actors By Movies – Stream#collect(Collectors#groupingBy())
private static Map<String, List<Actor>> getActorsGroupedByMovie() {
return getAllActors().stream()
.collect(Collectors.groupingBy(Actor::movie));
}
groupBy (MOVIE) :
- Angels Life:
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Penelope, lastName=Guiness, gender=F, movie=Angels Life, age=30]
- Actor[firstName=Cuba, lastName=Olivier, gender=M, movie=Angels Life, age=42]
- Actor[firstName=Jennifer, lastName=Davis, gender=F, movie=Angels Life, age=28]
- Actor[firstName=Grace, lastName=Mostel, gender=F, movie=Angels Life, age=63]
Grouping Movies By Total of Actors – Stream#collect(Collectors#groupingBy())
private static Map<String, Long> countActorsGroupedByMovie() {
return getAllActors().stream()
.collect(Collectors.groupingBy(Actor::movie, Collectors.counting()));
}
groupBy(MOVIE) + count(ACTORS):
- Crossroads Casualties: 1
- Dracula Crystal: 1
- Waterfront Deliverance: 1
- Clash Freddy: 1
- Conquerer Nuts: 1
- Young Language: 1
- Hills Neighbors: 1
- Pacific Amistad: 1
- Bulworth Commandments: 1
- Angels Life: 5
Listing All Movies – Stream#map()
private static Collection<String> getMoviesFromActors() {
return getDistinctActors().stream()
.map(Actor::movie)
.collect(Collectors.toList());
}
map(MOVIE) :
- Angels Life
- Bulworth Commandments
- Angels Life
- Dracula Crystal
- Angels Life
- Young Language
- Crossroads Casualties
- Pacific Amistad
- Conquerer Nuts
- Angels Life
- Clash Freddy
- Waterfront Deliverance
- Hills Neighbors
Listing Distinct Actors’ Full Names – Stream#distinct()#map()#reduce()
private static String getActorsFullNames() {
return getActorsSortedByFirstNameAscAndLastNameAsc().stream()
.distinct()
.map(actor -> actor.firstName() + " " + actor.lastName())
.reduce("", (result, name) -> result.isEmpty() ? name : result + ", " + name);
}
reduce(first+last Name) : Bette Nicholson, Cuba Olivier, Ed Chase, Grace Mostel, Jennifer Davis, Joe Swank, Johnny Lollobrigida, Marta Guiness, Matthew Johansson, Nick Wahlberg, Penelope Bergen, Penelope Guiness, Uma Wood
Testing All Stream API Examples at Once
public static void main(String[] args) {
System.out.println("count : " + countActors());
System.out.println("count + distinct : " + countDistinctActors());
System.out.println("max (AGE) : " + getOldestActor());
System.out.println("min (AGE) : " + getYoungestActor());
System.out.println("average (AGE) : " + getAverageAgeOfAllActors());
System.out.println("average (AGE) + distinct: " + getAverageAgeOfDistinctActors());
System.out.println("filter (J) + forEach : ");
filterActorsByFirstNameStartingWith("J").stream()
.forEach(actor -> System.out.println(" - " + actor));
System.out.println("sorted + limit (3) : ");
getActorsSortedByFirstNameAscAndLastNameAscLimitedBy(3).stream()
.forEach(actor -> System.out.println(" - " +actor));
System.out.println("sorted + skip (9) : ");
getActorsSortedByFirstNameAscAndLastNameAscSkipingFirst(9).stream()
.forEach(actor -> System.out.println(" - " +actor));
System.out.println("sorted (first+last Name): ");
getActorsSortedByFirstNameAscAndLastNameAsc().stream()
.forEach(actor -> System.out.println(" - " +actor));
System.out.println("unsorted : ");
getDistinctActors().stream()
.forEach(actor -> System.out.println(" - " +actor));
System.out.println("filter (> 50) : ");
getActorsWithAgeGreaterThan(50).stream()
.forEach(actor -> System.out.println(" - " +actor));
System.out.println("groupBy (MOVIE) : ");
getActorsGroupedByMovie()
.forEach((movie, actors) -> {
if(actors.size() > 1){
System.out.println(" - " + movie + ":");
actors.stream()
.forEach(actor -> System.out.println(" - " + actor));
}
});
System.out.println("groupBy(MOVIE) + count(ACTORS): ");
countActorsGroupedByMovie()
.forEach((movie, count) -> {
System.out.println(" - " +movie + ": " + count);
});
System.out.println("map(MOVIE) : ");
getMoviesFromActors()
.forEach((movie) -> {
System.out.println(" - " +movie);
});
System.out.println("reduce(first+last Name) : " + getActorsFullNames());
}
Conclusion
In conclusion, the Java Stream API offers developers a modern and efficient way to manipulate collections of objects in Java programming. By embracing its features, developers can write cleaner, more maintainable code and unlock new possibilities for data processing. Whether you’re working with small or large datasets, exploring this Java API can greatly enhance your programming experience and productivity.
Experience the power of Java Stream API and elevate your coding skills today!
You can download a version of the code showcased in this article from my GitHub repository.
Check out another article about DSA.
Thank you for reading this article!
0 Comments