Stream's ultimate skills are shared to help you process your data efficiently, and Ali's bulls are using them

Visit the latest Internet factory interview questions, Java programmer interview strategies (preparation before interview, skills in interview) GitHub

I. Preface

Collectors were mentioned earlier in articles related to Collection remove element operations.I believe that many students are interested in this, so let's study Collectors today.

II. Role of Collectors

Collectors is an operation class added by Java 8, located atJava.util.streamUnder the bag.It summarizes elements according to different strategies, such as the simplest and most common way to put elements in variable containers such as Map, Set, List, and so on.Especially useful for Java 8 Stream Api.It provides a collect() method to finalize Stream streams to derive a result set based on various policies.Let's familiarize ourselves with Collectors with Stream.We 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 provide a series of static methods for us to use, usually with static imports.Next let's see what methods are available.

3.1 Type Induction

This is a series that summarizes elements into variable containers List, Map, Set, Collection, or ConcurrentMap.

Collectors.toList();
Collectors.toMap();
Collectors.toSet();
Collectors.toCollection();
Collectors.toConcurrentMap();

We can use Stream's collect method to convert to a familiar collection container based on the API provided above.Very simple. No more demonstrations here.

3.2 joining

Connect elements together by some rule.This method has three overloaded joining(CharSequence delimiter) and joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix)

//   Output FelordcnTomcatJettyUndertowResin
servers.stream().collect(Collectors.joining());
//   Output Felordcn,Tomcat,Jetty,Undertow,Resin
servers.stream().collect(Collectors.joining("," ));
//   Output [Felordcn,Tomcat,Jetty,Undertow,Resin]
servers.stream().collect(Collectors.joining(",", "[", "]"));

More often than not, the body in HttpServletRequest is read:

HttpServletRequest.getReader().lines().collect(Collectors.joining());

3.3 collectingAndThen

This method first performs an induction operation, then performs Function processing on the induction result to output a new result.

// For example, we'll capitalize servers joining, and the result is: FELORDCN,TOMCAT,JETTY,UNDERTOW,RESIN   
servers.stream.collect(Collectors.collectingAndThen(Collectors.joining(","), String::toUpperCase));

3.4 groupingBy

Grouping elements conditionally is similar to the group by usage in SQL, and Java is often recommended for grouping to reduce database pressure.groupingBy also has three overload methods
We group servers by length:

// Grouping eligible elements by string length maps a List into Map<Integer, List<String> with conditional length key
servers.stream.collect(Collectors.groupingBy(String::length))

What if I don't want Map's value to be a List?The above implementation actually calls the following:

//Map<Integer, Set<String>>
servers.stream.collect(Collectors.groupingBy(String::length, Collectors.toSet()))

What should I do if I consider synchronization security?Of course, use thread-safe synchronization containers. You can't use either of them.Don't worry!Let's deduce that the second is actually equivalent to the following:

Supplier<Map<Integer,Set<String>>> mapSupplier = HashMap::new;
Map<Integer,Set<String>> collect = servers.stream.collect(Collectors.groupingBy(String::length, mapSupplier, Collectors.toSet()));

That's great. We can't just provide a synchronous Map, so the problem is 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, another way Collectors deals with synchronization security issues, groupingByConcurrent, gives us a solution.Usage is similar to groupingBy.

3.5 partitioningBy

partitioningBy, as we've seen in the articles mentioned at the beginning of this article, can be seen as a special case of groupingBy, grouped based on Predicate policies.There are no more examples.

3.6 counting

This method summarizes the number of elements, which is very simple and will not be exemplified.

3.7 maxBy/minBy

These two methods provide operations to find size elements, which are compared based on the Comparator interface and return an Optional object.Let's get the minimum length element in servers:

// Jetty  
Optional<String> min = servers.stream.collect(Collectors.minBy(Comparator.comparingint(String::length)));

In fact, Resin length is also the smallest here, which follows the principle of "first in first".Of course Stream.min() It is easy to get the minimum length of elements.The same is true for maxBy.

3.8 summingInt/Double/Long

Used for cumulative calculations.Calculate the sum of an attribute of an element, similar to Mysql's sum function, such as calculating the sum of profits for each project, the sum of all salaries for this month, and so on.Let's calculate the sum of the lengths of strings in servers (for example, without considering other writings).

// Total length 32 
servers.stream.collect(Collectors.summingint(s -> s.length()));

3.9 summarizingInt/Double/Long

What should we do if we operate from chapters 3.6 to 3.8?Can't we get five Stream streams?So there are three methods: summarizingInt, summarizingDouble, and summarizingLong.
By extracting an attribute of an element, these three methods return a statistical object for that attribute of the element, corresponding to IntSummaryStatistics, DoubleSummaryStatistics, LongSummaryStatistics, respectively.We do statistics on the length of elements in servers:

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 contained five indicators: total, sum, minimum, maximum and average.

3.10 mapping

This method is to reprocess elements using Function and then summarize them using another Collector.For example, we remove the initial letters of the elements in servers and load them into a List.

// [elordcn, omcat, etty, ndertow, esin]
servers.stream.collect(Collectors.mapping(s -> s.substring(1), Collectors.toList()));

It's a bit like Stream map s before collect ing:

servers.stream.map(s -> s.substring(1)).collect(Collectors.toList());

3.11 reducing

This method is very useful!But if you want to know this, you must know its parameter BinaryOperator<T>.This is a functional interface that gives two quantities of the same type and returns a result of the same type as the two quantities. The pseudo expression is (T, T) -> T.The default is given to two implementations, maxBy and minBy, which compare sizes based on the comparer and return either the maximum or the minimum value, respectively.Of course, you can customize it flexibly.Then reducing understands that comparing elements eliminates one according to strategy, and reduce s the number of elements in succession.What's the use of this one?The Java authorities give 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))));

With the first example given, you can try using reducing to find the longest string.

This layer above finds the highest Person based on the Height property, and if the property has no initialization value or no data, it is likely that you will not get the result so Optional <Person> is given.If we give identity as a benchmark, then we will first do a BinaryOperator operation with that benchmark.
For example, we give people over 2 meters as identities.We can count the tallest person who is no less than 2 meters in each city. Of course, if no one is higher than 2 meters in this city, we return the baseline 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 point it is certain that a Person will be returned, at least if the baseline value identity is no longer Optional.

In other cases, we want to round Person's height first when reducing.This requires us to do a mapping process.Define a Function <? Super T,? Extends U> mapper to do this work.The logic above can then be changed to:

   Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
        Person identity = new Person();
        identity.setHeight(2.);
        identity.setName("identity");
        // Define map 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 have a detailed explanation of Collectors in Java 8.It would be more handy if you were familiar with the Collectors operation Stream.

Tags: Java Jetty Tomcat Attribute

Posted on Thu, 04 Jun 2020 12:57:37 -0400 by ulrikqk