
1. preface
yesterday in Collection Remove Element Operation Related articles mentioned Collectors
。I believe many students are interested in this, so let's study it today. Collectors
。
2. The role of Collectors
Collectors
is Java 8 Added operation class, located in java.util.stream
Pack it. It collects and summarizes elements based on different strategies. For example, the simplest and most commonly used one is to load elements.Map
、Set
、List
Wait for variable containers. especially for Java 8 Stream Api Very useful for speaking. it providescollect()
method to Stream
Stream termination operations derive result sets based on various policies. We use Stream
Come and get familiar with it Collectors
Okay. Let's still use yesterday's example:
List<String> servers = new ArrayList<>();
servers.add("Felordcn");
servers.add("Tomcat");
servers.add("Jetty");
servers.add("Undertow");
servers.add("Resin");
3. Methods of Collectors in Java 8
Collectors
A series of static methods are provided for us to use, which can usually be used by static import. Next, let's take a look at what methods are provided.
3.1 type induction
This is a series that sums up elements into variable containers List
、Map
、Set
、Collection
orConcurrentMap
。
Collectors.toList();
Collectors.toMap();
Collectors.toSet();
Collectors.toCollection();
Collectors.toConcurrentMap();
We can use the above API use Stream
the collect
Method to the familiar collection container. Very simple. No more demonstrations here.
3.2 joining
Connect elements with certain rules. There are three overloads for this method joining(CharSequence delimiter)
and joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
// Output FeldcnTomcatJettyUndertowResin
servers.stream().collect(Collectors.joining());
// Output Feldcn,Tomcat,Jetty,Undertow,Resin
servers.stream().collect(Collectors.joining("," ));
// Output [Felordcn,Tomcat,Jetty,Undertow,Resin]
servers.stream().collect(Collectors.joining(",", "[", "]"));
What is more used is reading HttpServletRequest
of body :
HttpServletRequest.getReader().lines().collect(Collectors.joining());
3.3 collectingAndThen
This method first performs an induction operation, and then performs the results of the induction. Function
Function processing outputs a new result.
//For example, if we add servers joining and convert it to capitalized, the result is: FELORDCN,TOMCAT,JETTY,UNDERTOW,RESIN
servers.stream.collect(Collectors.collectingAndThen(Collectors.joining(","), String::toUpperCase));
3.4 groupingBy
Group elements according to conditions, and SQL of group by
The usage has the same effect and is usually recommended Java Perform grouping processing to relieve database pressure.groupingBy
There are also three overloading methods
we will servers
Group by length:
//Groups by string length Eligible elements will form a List and be mapped to Map Integer, List String
servers.stream.collect(Collectors.groupingBy(String::length))
if I don't want Map
the value
for List
What should I do? The above implementation actually calls the following methods:
//Map<Integer, Set<String>>
servers.stream.collect(Collectors.groupingBy(String::length, Collectors.toSet()))
What if I want to consider synchronization security issues? Of course, if you use a thread-safe synchronization container, you won't be able to use the first two! Don't rush! Let's infer that the second method is actually equivalent to the following writing:
Supplier<Map<Integer,Set<String>>> mapSupplier = HashMap::new;
Map<Integer,Set<String>> collect = servers.stream.collect(Collectors.groupingBy(String::length, mapSupplier, Collectors.toSet()));
This is very easy to do, we provide a synchronization Map
That was enough, and the problem was solved:
Supplier<Map<Integer, Set<String>>> mapSupplier = () -> Collections.synchronizedMap(new HashMap<>());
Map<Integer, Set<String>> collect = servers.stream.collect(Collectors.groupingBy(String::length, mapSupplier, Collectors.toSet()));
In fact, synchronization security issues Collectors
another method of groupingByConcurrent
Provides us with a solution. usage and groupingBy
Pretty much.
3.5 partitioningBy
partitioningBy
We have already seen it in the article mentioned at the beginning of this article, which can be seen as groupingBy
A special case of, based on the assertion (Predicate
) Strategic grouping. Examples will not be given here.
3.6 counting
This method summarizes the number of elements, which is very simple and will not be given examples.
3.7 maxBy/minBy
These two methods each provide operations to find size elements and are based on the comparator interface Comparator
To compare, what returns is a Optional
object. us to seek servers
Element with the smallest length in:
// Jetty
Optional<String> min = servers.stream.collect(Collectors.minBy(Comparator.comparingInt(String::length)));
this place Resin
The length is also the smallest, and the principle of "first impressions" is followed here. of course Stream.min()
It is easy to obtain elements of minimum length.maxBy
The same thing.
3.8 summingInt/Double/Long
Used for cumulative calculations. Calculate the sum of an attribute of an element, similar to Mysql the sum
Functions, such as calculating the total profits of each project, calculating the total salary for this month, etc. Let's do the calculations here servers
The sum of the lengths of the strings in (other writing methods are not considered for example).
//Total length 32
servers.stream.collect(Collectors.summingInt(s -> s.length()));
3.9 summarizingInt/Double/Long
if we 3.6 Chapter-Chapter 3.8 What should I do with the results of the operation? Can we make five? Stream
Flow? so there is summarizingInt
、summarizingDouble
、summarizingLong
Three methods.
These three methods extract a certain attribute of an element, and return a statistical data object for that attribute of the element, respectively corresponding to IntSummaryStatistics
、DoubleSummaryStatistics
、LongSummaryStatistics
。we servers
Calculate the length of the element in:
DoubleSummaryStatistics doubleSummaryStatistics = servers.stream.collect(Collectors.summarizingDouble(String::length));
// {count=5, sum=32.000000, min=5.000000, average=6.400000, max=8.000000}
System.out.println("doubleSummaryStatistics.toString() = " + doubleSummaryStatistics.toString());
results DoubleSummaryStatistics
featured among Total, total, minimum, maximum, average Five indicators.
3.10 mapping
This method uses the element first Function
Perform a reprocessing operation and then use anotherCollector
Summarize. For example, we remove first servers
First letters of the elements in, and then load them into List
。
// [elordcn, omcat, etty, ndertow, esin]
servers.stream.collect(Collectors.mapping(s -> s.substring(1), Collectors.toList()));
somewhat similar Stream
he first had his map
Operation is resumed collect
:
servers.stream.map(s -> s.substring(1)).collect(Collectors.toList());
3.11 reducing
This method is very useful! But if you want to understand this, you have to understand the parameters. BinaryOperator<T>
。This is a functional interface that returns a result of the same type to two quantities. The pseudo-expression is (T,T) -> T
。Two implementations are given by default maxBy
and minBy
, compare the sizes based on the comparator and return the maximum or minimum value respectively. Of course, you can customize it flexibly. then reducing
It is easy to understand. Compare two elements and eliminate one element according to the strategy. As the round progresses, the number of elements is reduce
of. So what's the use of this? Java officially gave an example: counting the tallest people in each city.
Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
Map<String, Optional<Person>> tallestByCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity, Collectors.reducing(BinaryOperator.maxBy(byHeight))));
Combined with the examples given at the beginning, you can use reducing
Try finding the longest string.
The upper layer is based on Height
Find the highest attribute Person
, and if this property has no initialization value or no data, it is very likely that the result will not be available, so what is given is Optional<Person>
。If we give identity
Make a benchmark value, then we will first follow this benchmark value BinaryOperator
Operation.
For example, if we give actions to people higher than 2 meters identity
。We can count the tallest person in each city who is no less than 2 meters. Of course, if no one in the city is more than 2 meters, we will return to the benchmark value.identity
:
Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
Person identity= new Person();
identity.setHeight(2.);
identity.setName("identity");
Map<String, Person> collect = persons.stream()
.collect(Collectors.groupingBy(Person::getCity, Collectors.reducing(identity, BinaryOperator.maxBy(byHeight))));
At this time, I was sure that one would be returned Person
Well, at least it will be a benchmark valueidentity
is no longer Optional
。
There are still some situations where we want to reducing
with your Person
Round your height first. This requires us to do a mapping process. define a Function<? super T, ? extends U> mapper
Come do this job. Then the above logic can be changed to:
Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
Person identity = new Person();
identity.setHeight(2.);
identity.setName("identity");
//Define mapping processing rounding
Function<Person, Person> mapper = ps -> {
Double height = ps.getHeight();
BigDecimal decimal = new BigDecimal(height);
Double d = decimal.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
ps.setHeight(d);
return ps;
};
Map<String, Person> collect = persons.stream()
.collect(Collectors.groupingBy(Person::getCity, Collectors.reducing(identity, mapper, BinaryOperator.maxBy(byHeight))));
4. summary
Today we are interested Java 8 of Collectors
A detailed explanation was given. If you are familiar with it Collectors
Operating Stream will be more convenient. course, in Java 8 after Java 9 and Java 12 in Collectors
There are new functions, and we will continue to explain when we have time later. Please pay attention!
Comments0