Java Stream Aggregate Functions Examples (Intermediate Operations)
- Details
- Written by Nam Ha Minh
- Last Updated on 14 June 2019   |   Print Email
In the tutorial Understand Java Stream API, you grasp the key concepts of the Java Stream API. You also saw some code examples illustrating some usages of stream operations, which are very useful for aggregate computations on collections such as filter, sum, average, sort, etc.
In this Java Stream tutorial, let’s look closer at these common aggregate functions in details.
Before begin, let’s see the data structure used in the examples. Given the following Personclass:
public class Person implements Comparable<Person> { private String firstName; private String lastName; private String email; private Gender gender; private int age; public Person() { } public Person(String firstName, String lastName, String email, Gender gender, int age) { this.firstName = firstName; this.lastName = lastName; this.email = email; this.gender = gender; this.age = age; } // geters and setters go here... public int compareTo(Person another) { return this.age - another.getAge(); } public String toString() { return this.firstName + " " + this.lastName; } }
Note that the getters and setters are removed for brevity (you should implement them completely), and the natural ordering of this class is based on age of the person (see its compareTo() method). Also, the toString() method returns the name of the person in form of first name followed by last name, so printing a Person object will show its full name.
The gender property is an enum which is declared as follows:
public enum Gender { MALE, FEMALE }
The sample data is hardcoded as follows:
List<Person> listPersons = new ArrayList<>(); listPersons.add(new Person("Alice", "Brown", "alice@gmail.com", Gender.FEMALE, 26)); listPersons.add(new Person("Bob", "Young", "bob@gmail.com", Gender.MALE, 32)); listPersons.add(new Person("Carol", "Hill", "carol@gmail.com", Gender.FEMALE, 23)); listPersons.add(new Person("David", "Green", "david@gmail.com", Gender.MALE, 39)); listPersons.add(new Person("Eric", "Young", "eric@gmail.com", Gender.MALE, 26)); listPersons.add(new Person("Frank", "Thompson", "frank@gmail.com", Gender.MALE, 33)); listPersons.add(new Person("Gibb", "Brown", "gibb@gmail.com", Gender.MALE, 27)); listPersons.add(new Person("Henry", "Baker", "henry@gmail.com", Gender.MALE, 30)); listPersons.add(new Person("Isabell", "Hill", "isabell@gmail.com", Gender.FEMALE, 22)); listPersons.add(new Person("Jane", "Smith", "jane@gmail.com", Gender.FEMALE, 24));
Okay, let’s examine the aggregate functions that are intermediate operations first. For terminal operations, we simple use the forEach operation that print out the current element in the result stream.
1. Java Stream filter operation example
The filter() operation returns a new stream that consists elements matching a given condition which is typically a boolean test in form of a Lambda expression.
The following example lists only male persons:
listPersons.stream() .filter(p -> p.getGender().equals(Gender.MALE)) .forEach(System.out::println);
Output:
Bob Young David Green Eric Young Frank Thompson Gibb Brown Henry Baker
The following code shows only female who are under 25:
listPersons.stream() .filter(p -> p.getGender().equals(Gender.FEMALE) && p.getAge() <= 25) .forEach(System.out::println);
Result:
Carol Hill Isabell Hill Jane Smith
2. Java Stream map operation example
The map operation returns a new stream consisting of elements which are the results of applying a given function to the elements of the current stream. For example, converting a stream of Objects to a stream of String or a stream of primitive numbers.
The Stream API provides 4 methods for the map operation:
- map(): transforms a stream of objects of type T to a stream of objects of type R.
- mapToInt(): transforms a stream of objects to a stream of int primitives.
- mapToLong(): transforms a stream of objects to a stream of long primitives.
- mapToDouble(): transforms a stream of objects to a stream of double primitives.
The following code maps each person to his/her respective email address:
listPersons.stream() .map(p -> p.getEmail()) .forEach(System.out::println);
Output:
alice@gmail.com bob@gmail.com carol@gmail.com david@gmail.com eric@gmail.com frank@gmail.com gibb@gmail.com henry@gmail.com isabell@gmail.com jane@gmail.com
The following example maps each person to his/her age:
listPersons.stream() .mapToInt(p -> p.getAge()) .forEach(age -> System.out.print(age + " - "));
Output:
26 - 32 - 23 - 39 - 26 - 33 - 27 - 30 - 22 - 24 -
The following example maps each person to his/her first name in uppercase:
listPersons.stream() .map(p -> p.getFirstName().toUpperCase()) .forEach(System.out::println);
Output:
ALICE BOB CAROL DAVID ERIC FRANK GIBB HENRY ISABELL JANE
3. Java Stream sorted operation example
The Stream API provides two overloads of the sorted operation that returns a new stream consisting elements sorted according to natural order or by a specified comparator:
- sorted(): sorts by natural order
- sorted(comparator): sorts by a comparator
The following example returns a stream of persons who are sorted by their age into ascending order:
listPersons.stream() .sorted() .forEach(p -> System.out.println(p + " - " + p.getAge()));
Look at the compareTo() method in the Person class, we see that the natural ordering is based on age:
public int compareTo(Person another) { return this.age - another.getAge(); }
Output of the above code:
Isabell Hill - 22 Carol Hill - 23 Jane Smith - 24 Alice Brown - 26 Eric Young - 26 Gibb Brown - 27 Henry Baker - 30 Bob Young - 32 Frank Thompson - 33 David Green - 39
The following code shows how to use a specified comparator to return a stream of persons who are sorted by their last name:
listPersons.stream() .sorted((p1, p2) -> p1.getLastName().compareTo(p2.getLastName())) .forEach(System.out::println);
Output:
Henry Baker Alice Brown Gibb Brown David Green Carol Hill Isabell Hill Jane Smith Frank Thompson Bob Young Eric Young
4. Java Stream distinct operation example
The distinct() operation returns a stream consisting of the distinct elements (no duplicates) by comparing objects via their equals() method.
The following example returns a stream of distinct numbers from an array source:
int[] numbers = {23, 58, 12, 23, 17, 29, 99, 98, 29, 12}; Arrays.stream(numbers).distinct().forEach(i -> System.out.print(i + " "));
Output:
23 58 12 17 29 99 98
Combining with the map and sorted operations, the following example shows distinct last names of the persons in the above list, and sorts them by alphabetic order:
listPersons.stream() .map(p -> p.getLastName()) .distinct() .sorted() .forEach(System.out::println);
Output:
Baker Brown Green Hill Smith Thompson Young
5. Java Stream limit operation example
The limit() operation returns a stream containing only a specified number of elements. Combining with the sorted() operation, the following example shows top 5 youngest persons:
listPersons.stream() .sorted() .limit(5) .forEach(System.out::println);
Output:
Isabell Hill Carol Hill Jane Smith Alice Brown Eric Young
6. Java Stream skip operation
The skip() operation returns a stream containing the remaining elements after discarding the first n elements of the stream.
Combining with the sorted and map operations, the following example finds the oldest age of the persons above:
System.out.print("The oldest age: "); listPersons.stream() .sorted() .map(p -> p.getAge()) .skip(listPersons.size() - 1) .forEach(System.out::println);
Output:
The oldest age: 39
As you can see, we can combine (chain) some aggregate functions together to achieve desired results. Such chaining is very common with streams operations. That makes streams powerful and flexible. I bet you will definitely love using it. I recommend you to read Java 8 in Action to master Streams programming in Java.
References:
Related Java Stream Tutorials
Other Java Collections Tutorials:
- Java List Tutorial
- Java Set Tutorial
- Java Map Tutorial
- Java Queue Tutorial
- 18 Java Collections and Generics Best Practices
- Understand equals and hashCode in Java
- Understand object ordering in Java
Comments
Great post! It helped me a lot! Thank you!
But it would be cool to also see some examples of flatMap() operation, which flattens a normal map() operation