Bhanu Prakash
3 min readJun 12, 2021

--

Good ways to use Java Stream API with a Utility Class

Java Stream API provides many inbuilt functions that drastically reduce manual effort, say, filtering, sorting, mapping.. etc for any type of collections.

But there is always manual effort when you are working with big enterprise applications or if the applications are too big with many model classes and many filtering and sorting operations going in there.

Stream API is there to do all those things for us however it also generates so much repeated code which is not so good when you wanna read it after 3 months. Let’s check how that looks with an example.

List<Customer> customers = new ArrayList<>();
// add few customers here

Now that I have list of customers, I want to separate all fields into respective lists to use them for a different purpose.

List<Integer> ids = customers.stream()
.map(Customer::getId)
.collect(Collectors.toList());
List<String> names = customers.stream()
.map(Customer::getName)
.collect(Collectors.toList());
List<String> addresses = customers.stream()
.map(Customer::getAddress)
.collect(Collectors.toList());

Oh My God! How many times do I need to write customers.stream().collect()... that's it I can't now.

How can we not write same words again and again? There’s always a utility class that comes to our rescue. Let’s have a look how we can build one for the stream API.

Let’s see how this goes.. all you need is a generic class that can handle these collect, filter, map and many more.. just once..

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public class StreamUtility { public static <T> List<T> toList(T[] array) {
return Arrays.stream(array)
.collect(Collectors.toList());
}

Okay, let’s try to understand this toList function. What this function does is it takes input as an array of any type, and it simply converts to list of that type using Arrays and stream. Now, how can we use this?

If we wanna convert an array to list then we have to write the Arrays call in the class we want, that’s ok if you just need it at couple of places, but what if we need that at more than 10–15 places, seems overhead, right? there you can simply call StreamUtility. Let’s see how that goes..

String[] array = new String[5];
// let's consider this array already has 5 items in it
now, to convert this to list of strings..
Old method:
List<String> list = Arrays.stream(array)
.stream()
.collect(Collectors.toList())
we don't want to do like above..List<String> list = StreamUtility.toList(array);

The last line of above block indicates the easy usage of a utility class. Write Once Use Anywhere. Some similar methods we can build in StreamUtility.java class are below..

public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate){   return list.stream()
.filter(predicate)
.collect(Collectors.toList());
}public static <T> T filterOne(List<T> list, Predicate<? super T> predicate){ return list.stream()
.filter(predicate)
.findFirst()
.orElse(null);
}public static <T, R> List<R> map(List<T> list, Function<T, R> map){ return list.stream()
.map(map)
.collect(Collectors.toList());
}

Let’s talk about these 3 methods one by one..

All three takes a list of any type as input and predicate and function accordingly..

filter method takes in a list of generic type and predicate to filter out the input list

filterOne method takes in a list of generic type and predicate but returns the first one of the list after filtering

map method takes in a list and a function, this can be used to separate a list of one respective field from the collection.

Examples for all three are as follows and a clean solution to the code that we saw earlier in this article.

List<Customer> cusList = StreamUtility.filter(customers, s -> s.getLName.equals("Tom"));Customer customer = StreamUtility.filterOne(customers, s -> s.getID.equals(5));List<Integer> ids = StreamUtility.map(customers , s -> s.getID());

This looks simple, easy to understand and a clean one. Now we have an understanding how a utility class can really clean things up for stream api.

We can extend the StreamUtility class further for compare, sort and many other things that stream api provides. This article gives a basic understanding on how we can use stream api with clean code.

Thanks for Reading.

--

--