Java8 Stream

Java8 Stream

Stream講解示例: 找出前3短的單詞并轉(zhuǎn)成大寫形式

List<String> words = Arrays.asList(
      "One",
      "Two",
      "Three",
      "Four",
      "Five",
      "Six"
  );

實現(xiàn)一:命令式——迭代:

  @Test
  public void test_takeTop3ShortWords_iterative() {
    
    List<String> filtered = new ArrayList<>();
    for(String word : words){
      if(word.length()<=4){
        filtered.add(word);
      }
    }
    
    filtered.sort(Comparator.comparing(String::length));
    
    List<String> top3 = filtered.subList(0, Math.min(3, filtered.size())); //節(jié)省了一個迭代
    
    List<String> result = new ArrayList<>(top3);
    for(String word : top3){
      result.add(word.toUpperCase());
    }
  }

缺點:

  • 代碼過于繁雜, 不太好直接看出意圖炕桨。
  • 代碼的中間變量過多,命名困難穗慕。

實現(xiàn)二:聲明式——stream

  @Test
  public void test_takeTop3ShortWords_stream(){
    
    List<String> result =  words.stream()
        .filter(s-> s.length()<=4)
        .sorted(Comparator.comparing(String::length))
        .map(String::toUpperCase)
        .limit(3)
        .collect(Collectors.toList());
  }

Stream的實現(xiàn)原理

操作的分類

操作的分類

操作的串聯(lián)

  1. 通過相關(guān)的操作對象PipelineHelper的構(gòu)造函數(shù),將操作先后關(guān)系維護起來(是反向的),維護一個代碼塊Sink鏈?zhǔn)浇Y(jié)構(gòu): D(C(B(A)))
  2. 調(diào)用wrapSink,將代碼塊正向串連起來: A->B->C->D
  3. 分別調(diào)用begin、foreach accecpt, end 代碼塊

操作的協(xié)作契約

interface Sink<T> extends Consumer<T> {
    void begin(long size); //執(zhí)行一些初始化工作眠寿,如排序時要建一個臨時表用于存儲排序后的數(shù)據(jù)
    void accept(T t); //繼承自Consumer,指明如何處理單個數(shù)據(jù)红选。
    void end(); //指明本操作結(jié)束時(所有數(shù)據(jù)都已經(jīng)處理完)澜公,如何進行后續(xù)的處理姆另。
    boolean cancellationRequested(); //當(dāng)下游不再需要更多數(shù)據(jù)時喇肋,可以用這個通知到上游操作坟乾。一般為短路操作。
}

自帶拆分功能的新版迭代器-數(shù)據(jù)流的驅(qū)動器

public interface Iterator<E> {
    boolean hasNext();  //是否還有更多數(shù)據(jù)
    E next(); //獲取下一個數(shù)據(jù)
    void remove(); //刪除最近一個數(shù)據(jù)
    
    default void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (hasNext())
                    action.accept(next());
    }
}
public interface Spliterator<T> {

    long estimateSize(); //估算還有多少數(shù)據(jù)待迭代
    boolean tryAdvance(Consumer<? super T> action); //處理單個數(shù)據(jù)
    Spliterator<T> trySplit(); //用于并行流分解子任務(wù)

    default void forEachRemaining(Consumer<? super T> action) {//默認(rèn)調(diào)用tryAdvance去遍歷蝶防,類似foreach
        do { } while (tryAdvance(action));
    }
}

流程示例

流程示例

Collection.stream()

  • StreamSupport.stream(spliterator(), false)
    • Spliterators.spliterator(this, 0)
    • new ReferencePipeline.Head

AbstractPipeline

AbstractPipeline(AbstractPipeline<?, E_IN, ?> previousStage, int opFlags) {
        if (previousStage.linkedOrConsumed)
                throw new IllegalStateException(MSG_STREAM_LINKED);
        previousStage.linkedOrConsumed = true;
        previousStage.nextStage = this;

        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;
}
        
@Override
final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) {
        copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator);
        return sink;
}

 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;
}

        @Override
final <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);
        }
}

Spliterator

class ArraySpliterator<E> implements Spliterator<E> {

        @SuppressWarnings("unchecked")
        @Override
        public void forEachRemaining(Consumer<? super T> action) {
            Object[] a; int i, hi; // hoist accesses and checks from loop
            if (action == null)
                throw new NullPointerException();
            if ((a = array).length >= (hi = fence) &&
                (i = index) >= 0 && i < (index = hi)) {
                do { action.accept((T)a[i]); } while (++i < hi);
            }
        }
}

filter

    @Override
    public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
        Objects.requireNonNull(predicate);
        return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SIZED) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                    @Override
                    public void begin(long size) {
                        downstream.begin(-1);
                    }

                    @Override
                    public void accept(P_OUT u) {
                        if (predicate.test(u))
                            downstream.accept(u);
                    }
                };
            }
        };
    }

sorted

  • SortedOps.makeRef(this)
class OfRef<T> extends ReferencePipeline.StatefulOp<T, T> {
        @Override
        public Sink<T> opWrapSink(int flags, Sink<T> sink) {
                Objects.requireNonNull(sink);

                // If the input is already naturally sorted and this operation
                // also naturally sorted then this is a no-op
                if (StreamOpFlag.SORTED.isKnown(flags) && isNaturalSort)
                        return sink;
                else if (StreamOpFlag.SIZED.isKnown(flags))
                        return new SizedRefSortingSink<>(sink, comparator);
                else
                        return new RefSortingSink<>(sink, comparator);
        }
}               
class RefSortingSink<T> extends AbstractRefSortingSink<T> {
        private ArrayList<T> list;

        RefSortingSink(Sink<? super T> sink, Comparator<? super T> comparator) {
            super(sink, comparator);
        }

        @Override
        public void begin(long size) {
            if (size >= Nodes.MAX_ARRAY_SIZE)
                throw new IllegalArgumentException(Nodes.BAD_SIZE);
            list = (size >= 0) ? new ArrayList<T>((int) size) : new ArrayList<T>();
        }

        @Override
        public void end() {
            list.sort(comparator);
            downstream.begin(list.size());
            if (!cancellationWasRequested) {
                list.forEach(downstream::accept);
            }
            else {
                for (T t : list) {
                    if (downstream.cancellationRequested()) break;
                    downstream.accept(t);
                }
            }
            downstream.end();
            list = null;
        }

        @Override
        public void accept(T t) {
            list.add(t);
        }
    }

map

    @Override
    @SuppressWarnings("unchecked")
    public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
        Objects.requireNonNull(mapper);
        return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
                return new Sink.ChainedReference<P_OUT, R>(sink) {
                    @Override
                    public void accept(P_OUT u) {
                        downstream.accept(mapper.apply(u));
                    }
                };
            }
        };
    }

limit

 Sink<T> opWrapSink(int flags, Sink<T> sink) {
                return new Sink.ChainedReference<T, T>(sink) {
                    long n = skip;
                    long m = limit >= 0 ? limit : Long.MAX_VALUE;

                    @Override
                    public void begin(long size) {
                        downstream.begin(calcSize(size, skip, m));
                    }

                    @Override
                    public void accept(T t) {
                        if (n == 0) {
                            if (m > 0) {
                                m--;
                                downstream.accept(t);
                            }
                        }
                        else {
                            n--;
                        }
                    }

                    @Override
                    public boolean cancellationRequested() {
                        return m == 0 || downstream.cancellationRequested();
                    }
                };
            }

collect

ReduceOp

 @Override
    public <P_IN> R evaluateSequential(PipelineHelper<T> helper, Spliterator<P_IN> spliterator) {
            return helper.wrapAndCopyInto(makeSink(), spliterator).get();  //new ReducingSink()
    }
        
class ReducingSink extends Box<R> implements AccumulatingSink<T, R, ReducingSink> {
        @Override
        public void begin(long size) {
                state = seedFactory.get();
        }

        @Override
        public void accept(T t) {
                accumulator.accept(state, t);
        }

        @Override
        public void combine(ReducingSink other) {
                reducer.accept(state, other.state);
        }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甚侣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子间学,更是在濱河造成了極大的恐慌殷费,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低葫,死亡現(xiàn)場離奇詭異详羡,居然都是意外死亡,警方通過查閱死者的電腦和手機嘿悬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門实柠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人善涨,你說我怎么就攤上這事窒盐。” “怎么了钢拧?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵蟹漓,是天一觀的道長。 經(jīng)常有香客問我源内,道長葡粒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任姿锭,我火速辦了婚禮塔鳍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呻此。我一直安慰自己轮纫,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布焚鲜。 她就那樣靜靜地躺著掌唾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪忿磅。 梳的紋絲不亂的頭發(fā)上糯彬,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音葱她,去河邊找鬼撩扒。 笑死,一個胖子當(dāng)著我的面吹牛吨些,可吹牛的內(nèi)容都是我干的搓谆。 我是一名探鬼主播炒辉,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泉手!你這毒婦竟也來了黔寇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斩萌,失蹤者是張志新(化名)和其女友劉穎缝裤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颊郎,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡憋飞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了姆吭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀崭。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猾编,靈堂內(nèi)的尸體忽然破棺而出瘤睹,到底是詐尸還是另有隱情,我是刑警寧澤答倡,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布轰传,位于F島的核電站,受9級特大地震影響瘪撇,放射性物質(zhì)發(fā)生泄漏获茬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一倔既、第九天 我趴在偏房一處隱蔽的房頂上張望恕曲。 院中可真熱鬧,春花似錦渤涌、人聲如沸佩谣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茸俭。三九已至,卻和暖如春安皱,著一層夾襖步出監(jiān)牢的瞬間调鬓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工酌伊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留腾窝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像虹脯,于是被迫代替她去往敵國和親辜贵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自: Java 8 中的 Streams API 詳解 為什么需要 Stream Stream 作為 Java ...
    普度眾生的面癱青年閱讀 2,919評論 0 11
  • Int Double Long 設(shè)置特定的stream類型归形, 提高性能,增加特定的函數(shù) 無存儲鼻由。stream不是一...
    patrick002閱讀 1,274評論 0 0
  • 一 基礎(chǔ)篇 1.1 Java基礎(chǔ) 面向?qū)ο蟮奶卣鞒橄?將一類對象的共同特征總結(jié)出來構(gòu)建類的過程暇榴。繼承:對已有類的一...
    essential_note閱讀 696評論 0 0
  • 剛剛看了一下自己寫的文章,居然沒有過千字的蕉世,就這樣的速度蔼紧,就這樣隔一個月才寫上的幾個字,什么時候才能成為想象中的自...
    鉤鉤手閱讀 110評論 0 1
  • 我明白你會來狠轻,所以我等奸例。——沈從文 人的一生可以遇到八萬人向楼,但是最后陪在你身邊的也不過是寥寥無幾查吊,有的人會日趕夜趕...
    茶不二閱讀 243評論 0 2