Code
1 public static void Main (string[] args) { 2 stream.of (" D2 "," A2 "," B1 "," B3 "," C " 4 System.out.printf (" Sort:%s ; %s\n " 5 S1.compareto (S2); 6 7
8 }
Execution results
SORT:A2; D2sort:b1; A2sort:b1; D2sort:b1; A2sort:b3; B1SORT:B3; D2SORT:C; B3SORT:C; D2a2b1b3cd2
See the results are not calm, so decided to debug a look at the internal packaging of which sort algorithm, this debugging very, found the stream of the call chain is a bit strange:
The above code takes advantage of the stream concept in Java8, and during the actual debugging process, you will find that it is not possible to go directly to the sort section from sorted (), which leads to this article.
Analysis
If you remove the . ForEach (system.out::p rintln) from the above code, you will notice that the sorted () function is ignored and will not execute at all, which involves the execution of the stream.
Call chain records are two major parts:
The first part: sorted ()
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/ Referencepipeline.java publicfinalSuper p_out> Comparator) { Return sortedops.makeref (this, comparator);}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/Sortedops.javaStatic<T> stream<t> makeref (abstractpipeline<?, T,?>Upstream, Comparator<?SuperT>comparator) { return NewOfref<>(upstream, comparator);} Ofref (Abstractpipeline<?, T,?> upstream, comparator<?SuperT>comparator) { Super(upstream, streamshape.reference, streamopflag.is_ordered|streamopflag.not_sorted); This. Isnaturalsort =false; This. Comparator =Objects.requirenonnull (comparator);}Part II: foreach ()
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/ Referencepipeline.javapublicvoidSuper p_out> action) { false ));}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/Abstractpipeline.javaFinal<R> R Evaluate (Terminalop<e_out, r>terminalop) { assertGetoutputshape () = =Terminalop.inputshape (); if(linkedorconsumed)Throw Newillegalstateexception (msg_stream_linked); Linkedorconsumed=true; returnIsparallel ()? Terminalop.evaluateparallel ( This, Sourcespliterator (Terminalop.getopflags ()): Terminalop.evaluatesequential ( This, Sourcespliterator (Terminalop.getopflags ()));}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/ForEachOps.java public <S> Void evaluatesequential (pipelinehelper<t> Helper, spliterator <S> spliterator) { return helper.wrapandcopyinto (this, Spliterator). Get ();}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/Abstractpipeline.javaFinal<p_in, Sextendssink<e_out>> s Wrapandcopyinto (s Sink, spliterator<p_in>spliterator) {Copyinto (Wrapsink (Objects.requirenonnull (sink)), spliterator); returnsink;}Final<P_IN> sink<p_in> Wrapsink (sink<e_out>sink) {objects.requirenonnull (sink); for(@SuppressWarnings ("Rawtypes") Abstractpipeline p=abstractpipeline. This; p.depth > 0; p=p.previousstage) {sink=P.opwrapsink (p.previousstage.combinedflags, sink); } return(sink<p_in>) sink;}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/stream/Sortedops.java PublicSink<t> Opwrapsink (intFlags, sink<t>.sink) {objects.requirenonnull (sink); //If The input is already naturally sorted and this operation//also naturally sorted then the is a no-op if(StreamOpFlag.SORTED.isKnown (Flags) &&isnaturalsort)returnsink; Else if(StreamOpFlag.SIZED.isKnown (flags))return NewSizedrefsortingsink<>(sink, comparator); Else return NewRefsortingsink<>(sink, comparator);} Sizedrefsortingsink (Sink<?SuperT> sink, comparator<?SuperT>comparator) { Super(sink, comparator);} Public voidEnd () {Arrays.sort (array,0, offset, comparator); Downstream.begin (offset); if(!cancellationwasrequested) { for(inti = 0; I < offset; i++) downstream.accept (Array[i]); } Else { for(inti = 0; I < offset &&!downstream.cancellationrequested (); i++) downstream.accept (Array[i]); } downstream.end (); Array=NULL;}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/Arrays.java Public Static<T>voidSort (t[] a,intFromIndex,intToindex, Comparator<?SuperT>c) {if(c = =NULL) {sort (A, fromIndex, Toindex); } Else{Rangecheck (a.length, FromIndex, Toindex); if(legacymergesort.userrequested) Legacymergesort (A, FromIndex, Toindex, C); ElseTimsort.sort (A, FromIndex, Toindex, C,NULL, 0, 0); }}
/library/java/javavirtualmachines/jdk1.8.0_171.jdk/contents/home/src.zip!/java/util/Timsort.javaStatic<T>voidSort (t[] a,intLointHi, comparator<SuperT>c, t[] work,intWorkbase,intWorklen) { assertc! =NULL&& A! =NULL&& lo >= 0 && lo <= hi && hi <=a.length; intnremaining = Hi-Lo; if(Nremaining < 2) return;//Arrays of size 0 and 1 is always sorted//If Array is small, does a "mini-timsort" with no merges if(Nremaining <Min_merge) { intInitrunlen =countrunandmakeascending (A, lo, Hi, c); Binarysort (A, lo, Hi, lo+Initrunlen, C); return; } /*** March over the array once, left to right, finding natural runs, * extending short natural runs to Minrun el Ements, and merging runs * to maintain stack invariant. */Timsort<T> ts =NewTimsort<>(A, C, work, Workbase, Worklen); intMinrun =minrunlength (nremaining); Do { //Identify Next Run intRunlen =countrunandmakeascending (A, lo, Hi, c); //If Run is short, extend to min (Minrun, nremaining) if(Runlen <Minrun) { intforce = nremaining <= minrun?Nremaining:minrun; Binarysort (A, lo, lo+ Force, lo +Runlen, C); Runlen=Force ; } //Push run onto Pending-run Stack, and maybe mergeTs.pushrun (lo, runlen); Ts.mergecollapse (); //Advance to find Next runLo + =Runlen; Nremaining-=Runlen; } while(Nremaining! = 0); //Merge All remaining runs to complete sort assertLo = =Hi; Ts.mergeforcecollapse (); assertTs.stacksize = = 1;}Part 3rd: CompareTo ()
This part will not be affixed, comparator
As can be seen from the call chain above, sorted () first enters foreach (), then calls the Timsort () sort algorithm in foreach (), and finally calls the comparator; Obviously, this call procedure is different from the program order. As a result of the first contact, the call chain is recorded, and then added to the deep principle.
A call chain analysis of Java8 Stream sorted ()