Important collector collector in the Java8

Source: Internet
Author: User
Tags addall stream api

Collector Introduction

Java8 's stream API makes it easy for us to classify data, and the style of functional programming allows us to write statistical code conveniently and intuitively.

For example:

stream<integer> stream = Stream.iterate (1, itemitem+2). Limit (6);Stream.filter(Item-Item >2).Maptoint(Item, Item *2).Skip(2).Limit(2).Sum();//.Reduce(0, (Val, val2)->val+val2);//system. Out. println (sum); summarystatistics = stream.filter (item-item > 2).  Maptoint2).  Skip2).  Summarystatisticsout. println (Summarystatistics.getaverage ());      

There is a collect (Collector C) method in the stream that receives an instance of Collector. Here we need to figure out the relationship between collector and collectors.

As a parameter of the Collect method, collector is an interface that is a mutable aggregation operation that accumulates input elements into a mutable result container; it converts the accumulated results to a final representation after all the elements have been processed (this is an optional operation);

If you do not understand, please continue to look down, combined with the following custom collector, I believe you can understand the content.

Collectors itself provides a common aggregation implementation of collector, collectors's inner class Collectorimpl implements the collector interface, and collectors itself is actually a factory.

Use of collector

Many times we use the Collectors ToList method, which provides various ways to accumulate the elements of a stream into aggregated results, such as counting, joining, Maxby, and so on. Here is an example:

Group List<student> List1 = Arrays. aslist (S1, S2, S3, S4, S5); Group BY name//map<string, list<student>> Map = List1. Stream (). Collect (Collectors. Groupingby (Student::getname)); Group by name first, then average map<string per group, double> Map = List1. Stream (). Collect (Collectors. Groupingby (Student::getname, collectors. Averagingdouble (Student::getscore))); System. Out. println (map); Partition Map<boolean, list<student>> map1 = List1. Stream (). Collect (Collectors. Partitioningby (Item-Item.getscore () >= 90)) .out.println (MAP1) .out.println ( " ------2-----") .stream () .collect (Collectors< Span class= "Hljs-preprocessor" >.groupingby (student::getname, Collectors.out.println (MAP2)              

This is similar to the concept of partitioning groupings in a database.

Collectors is designed to be composed; Many of the methods in {@link collectors} is functions that take a collector and produce a new collector.

Attach a sentence on the Javadoc, which indicates that the collection operation can be nested.

Custom Collector

As mentioned earlier, collectors itself provides a common aggregation implementation of collector, so programmers themselves can define their own aggregation implementations according to the circumstances.

First we look at the structure of the Collector interface

public interface Collector<T, A, R> {     Supplier<A> supplier(); BiConsumer<A, T> accumulator(); BinaryOperator<A> combiner(); Function<A, R> finisher(); Set<Characteristics> characteristics();}

Where generics represent the meaning of:
T: Represents the type of each element in the stream.
A: Represents the type of intermediate result container.
R: Represents the result type that is ultimately returned.

An enumeration class characteristics is also defined in collector, with three enumeration values, and understanding the meaning of these three values is critical to our own writing of the correct collector.

    • Characteristics.concurrent: Indicates that there is only one intermediate result, even in the case of a parallel stream. Therefore, the lambda expression returned by the Combiner method executes only if the parallel stream is present and the collector does not have the concurrent attribute (the intermediate result container has only one without merging).
    • Characteristics.unorder: Indicates that the elements in the stream are unordered.
    • Characteristics.identity_finish: Indicates that the intermediate result container type is consistent with the final result type, at which point the Finiser method is not called.

Let's take a look at the implementation of the ToList method in collectors.

public static <T> Collector<T, ?, List<T>> toList() {        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, CH_ID); }static final Set<Collector.Characteristics> CH_ID = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));

So, I wonder if you feel that way about your custom collector?

So how exactly do you implement a custom collector, let's take a look at the example below.

PublicClass Mycollectorimpl<t> implements Collector<t, Set<t>, set<t>> {@OverridePublic supplier<set<t>>Supplier () {return hashset<t>::New } @Overridepublic biconsumer<set<t>, t>Accumulator () {Return set<t>::add; } @OverridePublic binaryoperator<set<t>>Combiner () {Return (Set, item), {Set.addall (item);Returnset;}; } @Overridepublic function<set<t>, set<t>>finisher () {return function.identity ();} @Override public set<characteristics> characteristics () { return collections.unmodifiableset (Enumset.of (identity_finish,unordered));} public static void main (string[] args) {list<string> List = arrays.aslist (" hello ", set = (). Collect (new Mycollectorimpl<> ()); set.foreach (System. Out::p rintln); }}

This is a simple example where we add the Identity_finish feature to the Collector, at which point the lambda expression returned by the Finisher method is not called. This can also be verified from the source code.

Example 2:

PublicClassmycollectorimpl2<T>Implementscollector<Tset<T>,map<Tt>>{@Override public supplier<set<t>> Supplier () {return hashset<t>::New }@Override public biconsumer<set<t>, t> Accumulator () {Return set<t>::add; }@Override public binaryoperator<set<t>> combiner () {Return(Set1, Set2)->{Set1.addall (Set2);return Set1; }; }@Override public function<set<t>, Map<t, t>> finisher () {Return(set)->{hashmap<t, t> map =New HashMap ();>map.put (item, item));ReturnMap }; } @OverridePublicset<Characteristics>Characteristics() {ReturnCollections.Unmodifiableset(Enumset.Of (characteristics.unordered)); }PublicStaticvoidMain(string[] args) {list<String>List =Arrays.Aslist("Hello","World", "welcome"); hashset<string> set = new hashset<> (); set. addall (list); map<string, String> map = set. Stream ().  Collectnew mycollectorimpl2<> ()); system. out. println (map);}         

In this example, because the intermediate cumulative result container's type is inconsistent with the final type, it must be handled correctly in the Finisher method, otherwise the exception of the type conversion is definitely thrown.

Important collector collector in the Java8

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: 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.