Java Functional Programming (10): Collector _java

Source: Internet
Author: User
Tags addall

We've used several collect () methods to spell the elements returned by the stream as ArrayList. This is a reduce operation that is useful for converting a set to another type (usually a mutable set). The Collect () function, if used in conjunction with some of the methods in the Collectors tool class, provides great convenience, as we will introduce in this section.

Let's continue using the previous person list as an example to see what the Collect () method is capable of. Let's say we want to find all people older than 20 from the original list. The following versions are implemented using the variability and foreach () Methods:

Copy Code code as follows:

list<person> OlderThan20 = new arraylist<> (); People.stream ()
. Filter (Person-> person.getage () > 20)
. ForEach (person-> olderthan20.add); System.out.println ("People older than:" + olderThan20);

We use the filter () method to filter out all people older than 20 from the list. Then, in the Foreach method, we add the element to a ArrayList that has been initialized before. Let's take a look at the output of this code and refactor it in a moment.

Copy Code code as follows:

People older than: [Sara-21, Jane-21, Greg-35]

The results of the program output are right, but there is a small problem. First, adding elements to the collection is a low-level operation-it's imperative, not declarative. If we want to transform this iteration into concurrency, we have to consider the problem of thread safety--variability makes it difficult to parallelization. Fortunately, using the Collect () method can easily solve the problem. See how it is implemented.

The Collect () method accepts a stream and collects them into a result container. To complete this work, it needs to know three things:

+ How to create a result container (for example, using the Arraylist::new method) + How to add a single element to a container (such as using the Arraylist::add method) + How to merge one result set into another (for example, using the Arraylist::addall method)

The last piece is not required for serial operations; the goal of code design is to support both serial and parallel.

We provide these operations to the Collect method, allowing it to collect the filtered streams.

Copy Code code as follows:

List<person> OlderThan20 =
People.stream ()
. Filter (Person-> person.getage () > 20)
. Collect (Arraylist::new, Arraylist::add, Arraylist::addall);
System.out.println ("People older than:" + olderThan20);

The results of this code are the same as before, but there are many benefits to writing this.

First, our programming approach is more focused, more expressive, and clearly conveys the purpose of collecting the results in a ArrayList. The first parameter of collect () is a factory or producer, and the following argument is an operation to collect elements.

Second, it's easy to execute this iteration in parallel because we don't have an explicit modification in the code. We let the underlying library do the modification, and it itself handles the problem of collaboration and thread safety, even though the ArrayList itself is not thread-safe--well done.

If conditions permit, the Collect () method can add elements to different child lists in parallel, and then merge them into a large list in a thread-safe manner (the last parameter is used for the merge operation).

As we've seen, the benefits of using the Collect () method are far more useful than manually adding elements to a list. Let's look at an overloaded version of this method-it's simpler and more convenient-it's using a collector as an argument. This collector is an interface that includes the producer, the additive, and the Consolidator--in the previous version these operations were passed as separate parameters in the method--the use of collector was simpler and could be reused. The Collectors tool class provides a ToList method that generates a collector implementation to add elements to the ArrayList. Let's revise the previous code and use this collect () method.

Copy Code code as follows:

List<person> OlderThan20 =
People.stream ()
. Filter (Person-> person.getage () > 20)
. Collect (Collectors.tolist ());
System.out.println ("People older than:" + olderThan20);

There is more to this use than the concise version of the Collect () method of the Collectors tool class. There are several different ways to do different collections and additions to the Collectors tool class. For example, in addition to the ToList () method, and the Toset () method, which can be added to a set, the Tomap () method can be used to collect a Key-value collection, as well as the joining () method, which can be spliced into a string. We can also combine mapping (), Collectingandthen (), Minby (), Maxby () and Groupingby () to use the method.

Let's use the Groupingby () method to group the population by age.

Copy Code code as follows:

Map<integer, list<person>> peoplebyage =
People.stream ()
. Collect (Collectors.groupingby (person::getage));
System.out.println ("Grouped by Age:" + peoplebyage);

You can complete the grouping by simply invoking the Collect () method. Groupingby () accepts a lambda expression or a method reference-called a classification function-that returns the value of an attribute of an object that needs to be grouped. The elements in the invocation context are placed in a group based on the value returned by our function. You can see the results of the grouping in the output:

Copy Code code as follows:

Grouped by age: {35=[greg-35], 20=[john-20], 21=[sara-21, Jane-21]}

These people have been grouped by age.

In the previous example we grouped them according to the age of the population. A variant of the Groupingby () method can be grouped by multiple criteria. The simple Groupingby () method uses the classifier for element collection. And the Universal Groupingby () collector, you can specify a collector for each grouping. That is, the elements will go through different classifiers and collections in the process of collection, as we will see below.

To continue using the example above, we are not grouped by age, we only get people's names, sorted by their age.

Copy Code code as follows:

Map<integer, list<string>> nameofpeoplebyage =
People.stream ()
. Collect (
Groupingby (person::getage, Mapping (Person::getname, ToList ()));
System.out.println ("People grouped by age:" + nameofpeoplebyage);

This version of Groupingby () accepts two parameters: the first is age, which is the condition of grouping, and the second is a collector, which is the result returned by the mapping () function. These methods come from the Collectors tool class, where the code is statically imported. The mapping () method accepts two parameters, one for mapping attributes and one for objects to collect, such as list or set. Look at the output of the above code:

Copy Code code as follows:

People grouped by age: {35=[greg], 20=[john], 21=[sara, Jane]}

As you can see, people's names have been grouped by age.

Let's look at a combination of operations: Group by first letter of first name, then select the oldest in each group.

Copy Code code as follows:

comparator<person> byage = comparator.comparing (person::getage);
Map<character, optional<person>> oldestpersonofeachletter =
People.stream ()
. Collect (Groupingby (person-> person.getname (). CharAt (0),
Reducing (Binaryoperator.maxby (byage)));
System.out.println ("Oldest person of all letter:");
System.out.println (Oldestpersonofeachletter);

First we sorted by first letter of name. To achieve this, we passed a lambda expression as the first parameter of Groupingby (). This lambda expression is used to return the first letter of the name to be grouped. The second argument is no longer mapping (), but a reduce operation is performed. Within each grouping, it uses the Maxby () method to deliver the oldest one from all elements. This syntax looks a bit bloated because of the combination of many operations, but the whole thing reads like this: GROUP by initials, and then hand out the oldest in the group. Look at the output of this code, which lists the oldest person in the group name that starts with the specified letter.

Copy Code code as follows:

Oldest person of:
{s=optional[sara-21], g=optional[greg-35], j=optional[jane-21]}

We have learned the Collect () method and the power of the Collectors tool class. In the official document of your IDE or JDK, take a moment to study the collectors tool class and familiarize yourself with the various methods it offers. Here we will use lambda expressions to accomplish some of the filter implementations.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.