1. Stream Initial Experience
Let's take a look at how the stream is defined in Java:
A sequence of elements supporting sequential and parallel aggregate.
Let's interpret the sentence above: The stream is a collection of elements, which makes the stream look like a iterator; it can support sequential and parallel operations that converge on the original stream;
You can think of the stream as an advanced version of iterator. The original version of the iterator, the user can only one one to traverse the element and perform some action on it; the advanced version of the stream, the user simply gives the element that needs to be performed on its containing elements, such as "filter out the string of longer than 10", "get the first letter of each string" How these actions are applied to each element is good for the stream. (This cheats, the General people I do not tell him:) We read these may not have an intuitive understanding of the stream, MO urgent, we come to paragraph code.
Lists is a tool class in guava
list<integer> nums = lists.newarraylist (1,null,3,4,null,6);
Nums.stream (). filter (num-> num!= null). Count ();
The above code is to get a list of the number of elements that are not NULL. This code, though short, is a good entry-level example of how to use the stream, the so-called "though small spite". We are now going to dig into this example and you may be able to master the use of the stream after completion. 1.1 Profiling Stream general syntax
The picture is a parse of the stream example, you can see clearly: The original statement was divided into three colors of the box into three parts. The statement in the red box is where the life of a stream begins, and is responsible for creating a stream instance; The statement in the green box is the place that gives the stream soul, and converts a stream into another stream, The red box statement generates a stream that contains all the nums variables, and after the filter method of the green box, regenerates a stream that filters out all the null from the original nums list; The statement in the blue box is where the harvest is, The contents of the stream are aggregated into a value by some algorithm, in the case of getting the number of elements contained in the stream. If we do not understand this, then we can only use "nuclear weapons"-graphics, a map to the thousand words.
Here we summarize the basic steps to use the stream: Create the stream, convert the stream, change the original stream object each time, return a new Stream object (* * can have multiple conversions *), and Aggregate (Reduce) operations on the stream. Get the desired result; 2. Create Stream
The most commonly used creation stream has two approaches: static Factory method through the Stream interface (Note: JAVA8 interface can be static); The default method of collection interface (default method: Defaults methods, also a new attribute in Java8), is an interface with an implementation of the method, the following article will be introduced) –stream (), a collection object converted to stream 2.1 using the stream static method to create the stream
1. Of method: There are two overload methods, one accepts variable length parameters, one interface single value
stream<integer> Integerstream = Stream.of (1, 2, 3, 5);
stream<string> StringStream = Stream.of ("Taobao");
2. Generator method: Generates an infinite length stream whose elements are generated by a given supplier (this interface can be viewed as a factory of an object, each call returns a given type of object)
Stream.generate (New supplier<double> () {
@Override public
Double get () {return
math.random ();
}
});
Stream.generate (()-> math.random ());
Stream.generate (Math::random);
The three statements work the same way, using only the syntax of lambda expressions and method references to simplify the code. Each statement is actually generating an infinite length of the stream, where the value is random. This infinite-length stream is lazy to load, and generally this infinite-length stream is used in conjunction with the limit () method of the stream.
3. Iterate method: Also generates an infinite length of the stream, unlike generator, the generation of its elements is generated repeatedly by invoking the user-specified function on the given seed value (seed). The elements included can be considered: seed,f (seed), F (seed) infinite loop
Stream.iterate (1, item-> Item + 1). Limit. ForEach (system.out::p rintln);
This code first gets the stream of an infinite number of positive integers, and then takes out the first 10 prints. always remember to use the Limit method, otherwise you will print indefinitely. 2.2 Get stream via collection subclass
This is shown in the first example of this article to get its corresponding stream object from the list object, and if you look at Java doc, you can see that the collection interface has a stream method, so all of its subclasses can get the corresponding stream object.
Public interface Collection<e> extends iterable<e> {
//other method omits
default stream<e> Stream () { Return
Streamsupport.stream (Spliterator (), false);
}
3. Convert Stream
Converting a stream is actually converting a stream through some behavior into a new stream. There are several common conversion methods defined in the stream interface, and we select several common conversion methods to explain them.
1. Distinct: For the elements contained in the stream to redo (to the logical dependent elements of the Equals method), the newly generated stream has no duplicate elements;
Distinct method Diagram (* * All of the following schematics are thanks to the inspiration given by the pictures in Doc of [Rxjava] (Https://github.com/Netflix/RxJava) project, if the schematic expresses errors and inaccuracies, Please contact me directly. **):
2. Filter: For the elements contained in the stream using a given filter function for filtering operations, the newly generated stream contains only the elements that match the conditions;
Map of Filter Method:
3. Map: For the elements contained in the stream using the given transformation function for the conversion operation, the newly generated stream contains only the elements that the transformation generates. This method has three variants for the original type, respectively: Maptoint,maptolong and maptodouble. These three methods are also better understood, such as Maptoint is to convert the original stream into a new stream, and the elements in the newly generated stream are of type int. There are three variants that can eliminate the extra cost of automatic boxing/unboxing;
Map method Diagram:
4. Flatmap: And map Similar, the difference is that each element of its conversion to get the stream object, will be the target stream elements compressed into the parent set;
Flatmap method Diagram:
5. Peek: Generates a new stream that contains all the elements of the original stream, and provides a consumption function (consumer instance) that executes the given consumption function when each element of the new stream is consumed;
Peek method schematic:
6. Limit: The truncation of a stream to obtain its first n elements, if the original stream contains less than n the number of elements, then get all of its elements;
Limit method Diagram:
7. Skip: Returns a new stream with the remaining elements after discarding the first n elements of the original stream, and returns an empty stream if the original stream contains fewer than n elements;
Skip Method Sketch:
8. Together, together.
List<integer> nums = lists.newarraylist (1,1,null,2,3,4,null,5,6,7,8,9,10);
System.out.println ("Sum is:" +nums.stream (). filter (num-> num!= null).
Distinct (). maptoint (num-> num * 2).
Peek (System.out::p rintln). Skip (2). Limit (4). sum ());
This code illustrates all of the transformation methods described above (except Flatmap), and simply explains the meaning of this code: given an integer type list, get its corresponding stream object, then filter out null, then weight, then multiply each element by 2, Then each element is consumed by printing itself, skipping the first two elements, and finally going to the top four elements to add and calculate (explain a lot, like nonsense, because the basic look at the method name will know what to do.) This is one of the great benefits of declarative programming. )。 You can refer to the above explanations for each method to see what the final output is.
9. Performance problems
Some attentive students may have the question: in a stream for multiple conversion operations, each of the stream's elements are converted, and is executed many times, so the time complexity is a for loop in a for the cycle of all operations are done by the N (the number of conversions) times. This is not the case, conversion operations are lazy, a number of conversion operations will only be in the convergence of operations (see the next section) when the integration, a cycle of completion. We can simply understand that there is a set of operation functions in the stream, and each conversion operation is to put the transformation function into the set, loop the corresponding set of the stream at the time of the convergence operation, and then execute all the functions for each element. 4. Convergence (Reduce) Stream
Convergence of the word, is my own translation, if you have a better translation, you can leave a message below. In the official document is reduce, also known as fold.
Before we introduce the convergence operation, let's look at the definition in Java doc for it:
A reduction operation (also called a fold) takes a sequence of input elements and combines to a single them summary Lt by repeated application of a combining operation, such as finding the sum or maximum of a set of numbers, or Accumulati Ng elements into a list. The streams classes have multiple forms of general reduction operations, called reduce () and collect (), as OK as Multipl e specialized reduction forms such as SUM (), Max (), or count ().
A simple translation: convergence operations (also known as folding) accept an element sequence as input, and reuse a merge operation to combine the elements of a sequence into a single summarized result. For example, find the sum or maximum of a list of numbers, or accumulate these numbers into one list object. The stream interface has a number of common convergence operations, such as reduce () and collect (), and some specific purpose pooling operations, such as SUM (), Max (), and count (). Note: The sum method is not available for all stream objects, only Intstream, Longstream, and Doublestream are instances.
The following is a two-part introduction to Convergence: Variable convergence: The accumulation of input elements into a variable container, such as collection or StringBuilder; other convergence: Removing the rest of the variable aggregation is not usually done by repeatedly modifying a mutable object, This is done repeatedly by taking the previous convergence as the next entry. such as Reduce,count,allmatch, 4.1 variable convergence
A variable aggregation corresponds to only one method: Collect, as its name suggests, can collect elements from the stream into a result container (such as collection). First look at the definition of the most common collect method (and other override methods):
<R> R Collect (supplier<r> Supplier,
biconsumer<r,? Super t> Accumulator,
Biconsumer<r, R > Combiner);
Let's take a look at the meaning of these three parameters: Supplier Supplier is a factory function that is used to generate a new container; Biconsumer Accumulator is also a function that adds elements from the stream to the result container; Biconsumer Combiner is also a function that merges multiple result containers of the intermediate state into one (which is used when concurrency). Look dizzy. The code to the section.
List<integer> nums = lists.newarraylist (1,1,null,2,3,4,null,5,6,7,8,9,10);
list<integer> numswithoutnull = Nums.stream (). filter (num-> num!= null).
Collect (()-> new arraylist<integer> (),
(list, item)-> List.add (item),
(List1, List2)-> List1.addall (List2));
The above code is a list of integers of an element, filtering out all of the null, and then collecting the remaining elements into a new list. Take a closer look at the three parameters of the Collect method, which are lambda-form functions (* The above code can be simplified using method references and left to the reader to think for themselves *). The first function generates a new ArrayList instance, the second function accepts two parameters, the first is the ArrayList object that is generated earlier, and two is the element contained in the stream, and the function body joins the elements in the stream into the ArrayList object. The second function is called repeatedly until the elements of the original stream are consumed, and the third function accepts two parameters, both of which are ArrayList types, and the function body is to add the second ArrayList all to the first;
But the Collect method call above is also a bit too complicated, it doesn't matter. Let's take a look at another override version of the Collect method, which relies on [Collector] (http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html).
<r, a> R collect (collector< Super T, A, r> Collector);
It's so much more refreshing. Young, and the good news, JAVA8 also provided us with the Collector tool class –[collectors] (http://docs.oracle.com/javase/8/docs/api/java/util/stream/ collectors.html), which has defined some static factory methods, such as: Collectors.tocollection () collected into collection, Collectors.tolist () collection to the list and Collectors.toset () is collected into set. There are a lot of such static methods, here will not be introduced, we can go directly to see Javadoc. Here's a look at simplifying your code with collectors:
list<integer> numswithoutnull = Nums.stream (). filter (num-> num!= null).
Collect (Collectors.tolist ());
4.2 Other Gatherings
–reduce method: The reduce method is very generic, and the count,sum described later can be implemented using it. The reduce method has three override methods, this article describes two most commonly used, and the last one is left to the reader to learn. First look at the first form of the reduce method, whose method is defined as follows:
optional<t> reduce (binaryoperator<t> accumulator);
Accepts a binaryoperator type of argument that we can use in lambda expressions when used.
list<integer> ints = lists.newarraylist (1,2,3,4,5,6,7,8,9,10);
System.out.println ("INTs sum is:" + ints.stream (). Reduce (sum, item)-> Sum + Item). get ());
You can see that the reduce method accepts a function This function has two parameters, the first parameter is the return value (also known as the intermediate result) of the last function execution, and the second parameter is the element in the stream, which adds the two values together and assigns the first argument to the next execution of the function. NOTE: * * The first value of the first parameter is the first element of the stream, and the second is the second element of the stream. The return value type of this method is optional, a possible way to prevent NPE from appearing in the Java8, which is described in more detail here, which is simply considered a container, which may contain 0 or 1 objects.
The results of this process visualization are as follows:
The reduce method also has a very common variant:
t reduce (t identity, binaryoperator<t> Accumulator);
This definition is basically consistent and different: it allows the user to provide a cyclic calculation of the initial value, if the stream is empty, the value is returned directly. And this method does not return optional because it does not have null values. Here is a direct example, no longer explained.
list<integer> ints = lists.newarraylist (1,2,3,4,5,6,7,8,9,10);
System.out.println ("INTs sum is:" + ints.stream (). Reduce (0, (sum, item)-> sum + item);
–count method: Gets the number of elements in the stream. Relatively simple, here is a direct example, do not explain.