Java Stream principle Requirements
从"Apple" "Bug" "ABC" "Dog"中选出以A开头的名字,然后从中选出最长的一个,并输出其长度
1. The most straightforward implementation
Disadvantages
- Too many iterations
- Frequently produces intermediate results, performance unacceptable
2. Common wording
int0;for(String str : strings){ if(str.startsWith("A")){// 1. filter(), 保留以张开头的字符串 int len = str.length();// 2. mapToInt(), 转换成长度 longest = Math.max(len, longest);// 3. max(), 保留最长的长度 }}System.out.println(longest);
Disadvantages
- Specific business and algorithms mixed together, not conducive to code reuse
- The coupling is too strong, the code is not clear
3. Decoupling the responsibility chain model
public Chain {void proceed (Object object);}
public Forchain implements Chain {private Final Chain Chain; public forchain (Chain Chain) {this . chain = chain; } @Override public void (Object object) {list<string> List = (list<string>) object; for (String a:list) {if (A.startswith ( "a" )) Cha In.proceed (a); } }}
public Lengthchain implements Chain {private final Chain Chain; public lengthchain (Chain Chain) {this . chain = chain; } @Override public void (Object object) {string string = (String) object; Chain. proceed (String. length ()); }}
public Resultchain implements Chain {private Integer result = 0 ; @Override public void proceed (Object object) {Integer integer = (integer) object; result = Math. max (Integer,result); } public Integer getresult () {return re Sult; }}
public class Client { public static void main (string[] args) {Resultchain Resultchain = new resultchain (); Lengthchain Lengthchain = new lengthchain (Resultchain); Forchain Forchain = new forchain (Lengthchain); list<string> list = Arrays. aslist ( "Apple" , "Bug" , , "Dog" ); Forchain. proceed (list); System. out . println ( "result is" + resultchain. getresult ()); }}
4. Java Stream Implementation
OptionalInt max = Stream.of("Apple""Bug""ABC""Dog"). filter(e -> e.startsWith("A")). mapToInt(e -> e.length()). max();System.out.println("result is "+ max.getAsInt());
Advantages
- Developers need to focus on specific business, top-level algorithms are encapsulated in the framework
- Code structure is clear, code quantity is small, reduce the chance of error
5. Stream principle 5.1 stream vs. set comparison
Although the stream is very similar to the set frame in its performance, both are processing the data, but in fact they are completely different. A collection is a data structure that focuses on the organization of data in memory, which persists over time in memory, while the main focus of the stream is computing, not providing any storage space for the data, but only providing the results of the calculation through the pipeline.
5.2 Stream Operations Category
Intermediate action: Returns a new stream
- Stateful: You must wait for the previous operation to complete before you can proceed to the next step
- Stateless: This operation is not affected by the previous action
Terminate operation: return result
- Short circuit: returned when found
- Cost Short circuit: traverse all elements
The above operation determines that the stream must be built first and then executed, that is, deferred execution, when the need for results (terminal operation) began to execute the pipeline.
5.3 Stream Structure
5.4 How operations are recorded
- Head record start operation
- Statelessop Recording Intermediate operations
- Statefulop record a stateful intermediate operation
These three operations, when instantiated, refer back to an operation, and the latter, to form a doubly linked list, each step of the operation can know the previous step and the next operation.
For head:
Abstractpipeline(Spliterator<?> source,intSourceflags,BooleanParallel) { This.Previousstage=NULL; This.Sourcespliterator= Source; This.Sourcestage= This; This.Sourceoropflags= Sourceflags & Streamopflag.Stream_mask;//The following is an optimization of: //Streamopflag.combineopflags (Sourceoropflags, streamopflag.initial_ops_value); This.Combinedflags= (~ (sourceoropflags <<1)) & Streamopflag.Initial_ops_value; This.Depth=0; This.Parallel= parallel;}
For other actions:
Abstractpipeline(abstractpipeline<?, e_in,?> previousstage,intOpflags) {if(Previousstage.linkedorconsumed)Throw NewIllegalStateException (msg_stream_linked); Previousstage.linkedorconsumed=true; Previousstage.Nextstage= This;//Construct doubly linked list This.Previousstage= Previousstage; This.Sourceoropflags= Opflags & Streamopflag.Op_mask; This.Combinedflags= Streamopflag.Combineopflags(Opflags, Previousstage.Combinedflags); This.Sourcestage= Previousstage.Sourcestage;if(opisstateful()) Sourcestage.sourceanystateful=true; This.Depth= Previousstage.Depth+1;}
Example:
data.stream().filter(x -> x.length2).map(x -> x.replace(“三”,”五”)).sorted().filter(x -> x.contains(“五”)).forEach(System.out::println);
Stage
5.5 How the operation is superimposed
The sink is constructed sequentially from the termination operation, so that the sink chain is completed
finalwrapSink(Sink<E_OUT> sink) { Objects.requireNonNull(sink); // 依次构造sink for@SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth0; p=p.previousStage) { sink = p.opWrapSink(p.previousStage.combinedFlags, sink); } return (Sink<P_IN>) sink; }
Sink
- Call the Begin method of sink to notify the sink chain that the data is ready.
- Call Sink's Accept method to process the data
Call Sink's End method in turn to notify the data that the processing is complete
@Overridefinal <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {Objects.requireNonNull(wrappedSink);if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) { wrappedSink.begin(spliterator.getExactSizeIfKnown()); spliterator.forEachRemaining(wrappedSink); wrappedSink.end();}else { copyIntoWithCancel(wrappedSink, spliterator);}}
5.6 How to collect results
There is no need to collect results for foreach, and for collect results to be saved in the last sink, such operations will provide a GET method to fetch the data. The terminate operation implements the supplier Get method
@OverridepublicevaluateSequential(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) { return helper.wrapAndCopyInto(makeSink(), spliterator).get();}
publicinterface Supplier<T> { /** * Gets a result. * * @return a result */ get();}
interfaceextends Sink<T>, Supplier<R> { }
Java Stream principle