Collectors class

Collectors is a final class that extends the Object class. It provides reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc. Java Collectors class provides various methods to deal with elements.

1. Creating list: toList()

It is used to accumulate elements into a list. It will create a new list (It will not change the current list).

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            integers.stream().map(x -> x*x).collect(Collectors.toList());
                            // output: [1,4,9,16,25,36,36]
                      
                    

2. Creating set: toSet()

It is used to accumulate elements into a set, It will remove all the duplicate entries.

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            integers.stream().map(x -> x*x).collect(Collectors.toSet());
                            // output: [1,4,9,16,25,36]
                      
                    

3. Creating specific collection: toCollection()

We can accumulate data in any specific collection as well.

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            integers
                                .stream()
                                .filter(x -> x >2)
                                .collect(Collectors.toCollection(LinkedList::new));
                            // output: [3,4,5,6,6]
                      
                    

4. Counting elements: Counting()

It will return the number of elements present in the computed collection.

                      
                        List integers = Arrays.asList(1,2,3,4,5,6,6);
                            Long collect = integers
                                               .stream()
                                               .filter(x -> x <4)
                                               .collect(Collectors.counting());
                            // output: 3
                      
                    

5. Finding minimum value: minBy()

It will return the minimum value present in a list.

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            List<String> strings = Arrays.asList("alpha","beta","gamma");
                            integers
                                .stream()
                                .collect(Collectors.minBy(Comparator.naturalOrder()))
                                .get();
                            // output: 1
                            strings
                               .stream()
                               .collect(Collectors.minBy(Comparator.naturalOrder()))
                               .get();
                            // output: alpha
                      
                    

It will return 1 and alpha, as per the natural order of integers and string.
We can reverse the order using reverseOrder() method.

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            List<String> strings = Arrays.asList("alpha","beta","gamma");
                            integers
                                .stream()
                                .collect(Collectors.minBy(Comparator.reverseOrder()))
                                .get();
                            // output: 6
                            strings
                               .stream()
                               .collect(Collectors.minBy(Comparator.reverseOrder()))
                               .get();
                            // output: gamma
                      
                    

6. Finding maximum value: maxBy()

It is similar to the minimum value method, here we use maxBy() method to get the maximum value.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            strings
                               .stream()
                               .collect(Collectors.maxBy(Comparator.naturalOrder()))
                               .get();
                            // output: gamma
                      
                    

All the comparator logic which were there in minBy() also apply to maxBy().

7. Partitioning a list: partitioningBy()

It is used for partitioning a list into 2 lists and adding it to the map, 1 that satisfies a given condition and another which does not satisfy like separating odd numbers from the list. So it will make 2 entries in the map, 1 with true as key and odd numbers as value and 2nd with false as key and even numbers as value.

                      
                        List<String> strings = Arrays.asList("a","alpha","beta","gamma");
                            Map<Boolean, List<String>> collect1 = strings
                                      .stream()
                                      .collect(Collectors.partitioningBy(x -> x.length() > 2));
                            // output: {false=[a], true=[alpha, beta, gamma]}
                      
                    

Here we are separating the strings with lengths greater than 2 from the remaining strings.

8. Creating unmodifiable list: toUnmodifiableList()

It is used to create a read-only list. Any try to make a change in this unmodifiable list will result in UnsupportedOperationException.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            List<String> collect2 = strings
                                   .stream()
                                   .collect(Collectors.toUnmodifiableList());
                            // output: ["alpha","beta","gamma"]
                      
                    

9. Creating unmodifiable set: toUnmodifiableSet()

It is used to create a read-only set. Any try to make a change in this unmodifiable set will result in UnsupportedOperationException.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma","alpha");
                            Set<String> readOnlySet = strings
                                   .stream()
                                   .sorted()
                                   .collect(Collectors.toUnmodifiableSet());
                            // output: ["alpha","beta","gamma"]
                      
                    

10. Joining elements: joining()

Collectors can be used to create a string by joining all the elements of a collection, with or without any delimiter, suffix, and prefix.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            String collect3 = strings
                                 .stream()
                                 .distinct()
                                 .collect(Collectors.joining(","));
                            // output: alpha,beta,gamma
                            String collect4 = strings
                                 .stream()
                                 .map(s -> s.toString())
                                 .collect(Collectors.joining(",","[","]"));
                            // output: [alpha,beta,gamma]
                      
                    

In the first example we are joining string by passing a delimiter value (“,”) and in second we are passing the value of prefix and suffix.

11. Averaging long: averagingLong()

Finds the average value of a collection of long values.
NOTE: It will return a Double value, not a long value.

                      
                        List>Long< longValues = Arrays.asList(100l,200l,300l);
                            Double d1 = longValues
                                .stream()
                                .collect(Collectors.averagingLong(x -> x * 2));
                            // output: 400.0
                      
                    

12. Averaging int: averagingInt()

Finds the average value of a collection of integer values.
NOTE: It will also return a Double value, not an int value.

                      
                        List>Integer< integers = Arrays.asList(1,2,3,4,5,6,6);
                            Double d2 = integers
                                .stream()
                                .collect(Collectors.averagingInt(x -> x*2));
                            // output: 7.714285714285714
                      
                    

13. Averaging Double: averagingDouble()

Finds the average value of a collection of double values.

                      
                        List<Double> doubles = Arrays.asList(1.1,2.0,3.0,4.0,5.0,5.0);
                            Double d3 = doubles
                                .stream()
                                .collect(Collectors.averagingDouble(x -> x));
                            // output: 3.35
                      
                    

14. Creating Map: toMap()

Creates a map from the values of a collection.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            Map<String,Integer> map = strings
                                   .stream()
                                   .collect(Collectors
                                      .toMap(Function.identity(),String::length));
                            // output: {alpha=5, beta=4, gamma=5}
                      
                    

Here we created a map with list values as keys and the number of occurrences of the value in the list as the value.

15. Handling duplicates entries of the list while creating a map

A list can contain duplicate values, so If we want to create a map out of the list and want to use the list values as keys of the map then we need to resolve the duplicate keys. As a map only contains unique keys, we can use comparators to do that.

                      
                        List<String>  strings = Arrays.asList("alpha","beta","gamma","beta");
                            Map<String,Integer> map = strings
                                    .stream()
                                    .collect(Collectors
                                      .toMap(Function.identity(),String::length,(i1,i2) -> i1));
                            // output: {alpha=5, gamma=5, beta=4}
                      
                    

Here, Function.identity() is pointing to the list value, and i1, i2 are the values of the duplicate keys. We can keep a single value so, here we are selecting i1 but we can compute anything using these two values like adding them, comparing and selecting the greater one, etc.

16. Summing Integers: summingInt()

Finding the sum of all the integer values present in the list. It’s not always the sum of the initial collection, which we are using like in the below example we are using the list of strings and first, we are converting each string into an integer that is equal to its length and then adding all the lengths.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            Integer collect4 = strings
                                  .stream()
                                  .collect(Collectors.summingInt(String::length));
                            // output: 18
                      
                    

or direct list value sum

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            Integer sum = integers
                                .stream()
                                .collect(Collectors.summingInt(x -> x));
                            // output: 27
                      
                    

17. Summing Doubles: summingDouble()

Similar to summing integers, just it is used for double values.

                      
                        List<Double>  doubleValues = Arrays.asList(1.1,2.0,3.0,4.0,5.0,5.0);
                            Double sum = doubleValues
                                 .stream()
                                 .collect(Collectors.summingDouble(x ->x));
                            // output: 20.1
                      
                    

18. Summing Long: summingLong()

Same as the first two, used for adding long or int values. We can use summinglong() for int values as well, but we cannot use summingInt() for long values. It is based on the concept of typecasting, which data type can be cast in which one.

                      
                        List<Long> longValues = Arrays.asList(100l,200l,300l);
                            Long sum = longValues
                                .stream()
                                .collect(Collectors.summingLong(x ->x));
                            // output: 600
                      
                    

19. Summarizing Integer: summarizingInt()

It gives all the major arithmetic operation values of the values present in the collection like the average of all values, minimum value, maximum values, count, and sum of all values.

                      
                        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
                            IntSummaryStatistics stats = integers
                                      .stream()
                                      .collect(Collectors.summarizingInt(x -> x ));
                            //output: IntSummaryStatistics{count=7, sum=27, min=1, average=3.857143, max=6}
                      
                    

Now we can extract different values using get methods like:

                      
                        stats.getAverage();   // 3.857143
                        stats.getMax();       // 6
                        stats.getMin();       // 1
                        stats.getCount();     // 7
                        stats.getSum();       // 27
                      
                    

20. GroupingBy method: groupingBy()

GroupingBy() is an advance method to create a map out of any other collection. It itself is a very vast topic which we will cover in the next blog. SO here just for the completion let's see a few examples

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            Map<Integer, List<String>> collect = strings
                                      .stream()
                                      .collect(Collectors.groupingBy(String::length));
                            // output: {4=[beta], 5=[alpha, gamma]}
                      
                    

It will make the string length as key and a list of strings of that length as the value.

                      
                        List<String> strings = Arrays.asList("alpha","beta","gamma");
                            Map<Integer, LinkedList<String>> collect1 = strings
                                        .stream()
                                        .collect(Collectors.groupingBy(String::length, 
                                            Collectors.toCollection(LinkedList::new)));
                            // output: {4=[beta], 5=[alpha, gamma]}
                      
                    

Here we specified the type of list we want in the map (linked list).