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.
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]
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]
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]
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
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
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().
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.
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"]
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"]
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.
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
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
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
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.
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.
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
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
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
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
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).