Home Office Working Desk

Streams In Java

In Java, the streams provide us to make some functional-style operations on streams of data. For instance, reducing, filtering, grouping, sorting, etc. In this article, we will try and examine these operations that are used the most.

Let us create a list and filter them.

List<String> stringList = Arrays.asList("This is elem 1", "", "This is elem 2", "My data", "Temp");
stringList.stream().filter(e -> !e.isEmpty() && e.contains("elem")).forEach(System.out::println);
// This is elem 1
// This is elem 2

We can filter our list of elements easily. In this example, we printed the result. However, we can also keep the result in another list.

List<String> filteredList = stringList.stream().filter(e -> !e.isEmpty() && e.contains("elem")).collect(Collectors.toList());

If we need to eliminate duplicates in our stream of elements, we can use distinct.

List<String> stringList = Arrays.asList("This is elem 1", "Temp", "Temp");
// This is elem 1
// Temp

We eliminated the duplicates. However, sometimes, we may only need to know how many distinct elements there are. In this case, we can use count.

// 2

If the size of a list is longer than we need, we can limit it.

List<String> stringList = Arrays.asList("This is elem 1", "Temp 1", "Temp 2", "My data", "Another data");
// This is elem 1
// Temp 1
// Temp 2

If we need a single result after the stream operations, we can use reduction.

List<String> stringList = Arrays.asList("This ", "is ", "a ", "sentence", ".");
System.out.println(stringList.stream().reduce("", (prevRes, currElem) -> prevRes + currElem));
// This is a sentence.

If we need to apply some special operations on the stream of elements, we can use mapping.

List<String> stringList = Arrays.asList("This ", "is ", "a ", "sentence", ".");
// IS
// A
// .

Many times we need to sort our elements.

List<String> stringList = Arrays.asList("This ", "is ", "a ", "sentence", ".");
// .
// a
// is
// This
// sentence

In this example, we sorted our elements in ascending order according to their length.

Up to this point, we used simple streams of elements. However, most of the time, we need to deal with our custom objects. Let us apply some streams we learned, on our custom objects.

Let us write a class.

public class User {
    private String id;
    private String username;
    private Integer numberOfClaps;

    // constructor(s), getters, setters

Then create a list of users.

List<User> users = Arrays.asList(
    new User("111", "user1", 5),
    new User("222", "user2", 15),
    new User("333", "user3", 2),
    new User("444", "user4", 20),
    new User("555", "user5", 20)

Let us assume that we need only usernames. In this case, we can use mapping.


In another example, we assume that we need users who have more than 10 claps and we need to group them according to their claps. Then print to the screen.

users.stream().filter(e -> e.getNumberOfClaps() > 10).collect(Collectors.groupingBy(User::getNumberOfClaps)).forEach(
		(key, value) -> {
			System.out.println("Claps: " + key);
// Claps: 20
// user4
// user5
// Claps: 15
// user2

Also, we can keep the result in a map structure.

Map<Integer, List<User>> result = users.stream().filter(e -> e.getNumberOfClaps() > 10).collect(Collectors.groupingBy(User::getNumberOfClaps));

Of course, the streams are not limited to these examples. We can do many more operations with streams. We may continue to try and examine different operations in the next articles.