One of the fluent APIs that Java 8 brings us, is the Java 8 Stream API, which provides a practical and minimal interface to code, especially with the help of Java 8 Lambdas.
Today, we are going to write a simple utility class to convert and modify java collections with ease, by using the power of Java 8 Streams.
Utility classes are structures that contain reusable and stateless helper methods. We implement these methods for handling any kind of specific operations for specific purposes. Because of their stateless nature, we mostly prefer to define them as static.
First of all, let’s define a simple class:
Static Classes in Java
Static classes are classes that cannot be instantiated. As utility classes do not need to hold any state, it is appropriate to define them as static to prevent creating instances of them.
Unlike some other languages, in Java, we cannot use the static modifier for classes. Instead, we will use a private constructor to give the same ability to our utility classes:
Array to Collection Conversion
The first method of our utility class will be a generic method that simply converts a given array structure to java.util.Collection type.
We have two different behavioral types to return as java collections, one of them is List that is used when we need to preserve the order of the elements, the other one is Set that is used when we need to preserve the uniqueness of the elements.
First, let’s define a generic method that handles array to List conversion:
Power of Java 8 Stream API
Normally to implement this kind of method, we need to traverse the elements of an array and populate each of them to a newly created ArrayList object. However, thanks to the Java 8 Stream API, we can easily get rid of this sort of boilerplates.
So let’s implement our toList method:
We use the Arrays.stream() method to open a stream over the given array. Once we acquire the stream instance, we may operate over the stream by many provided methods like collect, filter, map, etc. We choose the method collect here to copy elements from an array to another structure with the help of predefined stream collectors.
Like toList method, let’s define a separate method for array to Set conversion:
Handling Primitive Types
With the help of generics we successfully handled for all object types but when it comes to primitive types of java we cannot use our generic methods. We see an error when we try to use with primitive-typed arrays and our java compiler complains about the argument types which are not applicable:
One of the ways of solving this problem is simply defining separate methods with primitive-typed arguments. We will use boxed method of streams to box every primitive element to its wrapper objects:
Similarly, we can define more methods in the same way for other remaining primitives like boolean, byte, char, short, float, etc.
And also we can define their Set versions that are pretty same:
Sometimes it might be important to preserve both the order and the uniqueness of the elements and we need to handle this with a single collection type. If we encounter this problem in java the LinkedHashSet collection type comes to rescue.
Let’s add an optional parameter to our ToSet method in order to return LinkedHashSet type instead of unordered HashSet:
The former method here simply uses the overloaded method of itself. By doing this, we not only provide a default value for preserveOrder parameter but also protect the backward compatibility of our utility methods. We set false to preserveOrder as default value here.
Collection to Collection Conversions
Conversion from a collection type to another collection type is also easily possible with streams. We can get streams from collections as well and we can perform List to Set conversion and vice versa.
Let’s define some methods to add this ability to our utility class:
Filtering Arrays and Collections
One of the handy methods of Stream API is filter method. This provides a comfortable way of filtering an array or collection and creating subsets of theirs. With the power of lambdas we can also customize the behavior.
Let’s define two methods to perform filtering on arrays or collections:
Next, let’s use this method to filter an array of strings by their first letters as the character ” a “:
Now, by running this code, we will see the outputs of the filtered elements:
Concatenate Elements into a String
Another ability that may be useful is printing the elements of collections or arrays. Most of the time, we use it for debugging purposes.
We can extend our utility class by adding some methods to simply joining the string representations of the elements. Plus, a custom separator and an optional limit parameter may be useful.
So, let’s define our join methods:
Then, let’s use our join method with a separator of comma and a limit parameter of 3:
Last, we will see the output, maximum of 3 elements joined:
In this tutorial, we explained how to implement a simple utility class for collections by the help of Java 8 Stream API.
There are many possible methods to implement which are likely to come in handy when we are dealing with collections.
So, what do you think about any other useful methods to include in our utility class? Just feel free to comment below!
All the code samples given in this tutorial are available over on GitHub.