How to Build a Custom Collector in Java?
Java Collector is the utility class that provides many helpful methods and functions for the collector interface. Mainly collector implementation is used with the stream collect() method. The collector interface was provided by Java 8 under the part of the newly introduced Java Stream API. This interface provides various methods to perform mutual reduction operations. The Mutable reduction operations perform arithmetic functions on the mathematical information in a stream to find minimum, maximum, average, or accumulate elements of a Stream into a Set or concatenate all the String elements from the Stream.
Steps to Create Custom Collector
To write custom collectors, we’re supposed to implement the interface with the below-mentioned methods. The collection usually happens in four steps provided by Streams API.
- Supplier(): This is the first step of the element collection process, and In this process, the container is created to hold the elements from the stream. The return type of this method is the supplier of container type.
- Accumulator(): This is the second step in which each element is added into the container created by Supplier Step. In this method, we have to return a BiConsumer function that accepts the container and every element from the Stream.
- Combiner(): This is the optional step, which is executed only when the stream is processed in a parallel era, and if the Stream is sequential, then this step will be skipped. The Combine step is used to combine all the elements into a single container. In this method, we’re supposed to return a Binary Operator function that combines two accumulated containers.
- Finish(): It is the last step in the collection process. It will execute only when all the elements in the stream are successfully accumulated in the supplier container. In this method, we can return a function to transform the accumulated and combined container into the final output.
Other than these methods, we have the characteristics() method to specify the characteristics of the Collector and the return type Enum values of a set of characteristics.
To illustrate this example, we’ll divide the code into three sections for better understanding. Let’s take an example in which we have a list of Employee objects, and we want to create a stream from it and collect the Employee objects as an immutable list of Triplets. Each of the triplets in the list will represent an employee, and it will have the age, first name, and last name of the employee.
In the example mentioned above, we’ve class named Employee_GFG consist private variable named id, firstname, lastname, year, Constructor, which initialize the variables and also have various functions setFirstName, getLastName, set LastName, getYear, setYear, etc. this function just set or get the values of the variable.
Now we have to implement the Collector interface. To create the class for collector methods for supplier, accumulator, and finisher as discussed above.
In the example mentioned above, we created a class named EmployeeCollector. Under that, we implemented a custom collector with triplet Integer, Integer, String, and written Supplier function that supplies a container to hold Stream elements and supplies a new ArrayList when it is invoked. BiConsumer function in this returning function gets the container, which is an ArrayList and a Student object from the stream, BinaryOperator function is combiner which takes to containers as arguments and returns one, last-second function name “Function” the container which is an ArrayList of student triplets and returns an Unmodifiable List.
Now, we will use our collector on employee streams. We will use the toEmployeeList() function in the collect() method.
[1,samarth,sharma,2019] [2,praful,john,2019] [3,goutam,verma,2015] [4,mohit,verma,2016]
Above is desired output from the code, which consist list of an employee with first name, last name, year, and id.