美文网首页
Java8 Stream

Java8 Stream

作者: zhackertop | 来源:发表于2018-06-27 18:14 被阅读0次

Java8 Stream

Stream讲解示例: 找出前3短的单词并转成大写形式

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

实现一:命令式——迭代:

  @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())); //节省了一个迭代
    
    List<String> result = new ArrayList<>(top3);
    for(String word : top3){
      result.add(word.toUpperCase());
    }
  }

缺点:

  • 代码过于繁杂, 不太好直接看出意图。
  • 代码的中间变量过多,命名困难。

实现二:声明式——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的实现原理

操作的分类

操作的分类

操作的串联

  1. 通过相关的操作对象PipelineHelper的构造函数,将操作先后关系维护起来(是反向的),维护一个代码块Sink链式结构: D(C(B(A)))
  2. 调用wrapSink,将代码块正向串连起来: A->B->C->D
  3. 分别调用begin、foreach accecpt, end 代码块

操作的协作契约

interface Sink<T> extends Consumer<T> {
    void begin(long size); //执行一些初始化工作,如排序时要建一个临时表用于存储排序后的数据
    void accept(T t); //继承自Consumer,指明如何处理单个数据。
    void end(); //指明本操作结束时(所有数据都已经处理完),如何进行后续的处理。
    boolean cancellationRequested(); //当下游不再需要更多数据时,可以用这个通知到上游操作。一般为短路操作。
}

自带拆分功能的新版迭代器-数据流的驱动器

public interface Iterator<E> {
    boolean hasNext();  //是否还有更多数据
    E next(); //获取下一个数据
    void remove(); //删除最近一个数据
    
    default void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (hasNext())
                    action.accept(next());
    }
}
public interface Spliterator<T> {

    long estimateSize(); //估算还有多少数据待迭代
    boolean tryAdvance(Consumer<? super T> action); //处理单个数据
    Spliterator<T> trySplit(); //用于并行流分解子任务

    default void forEachRemaining(Consumer<? super T> action) {//默认调用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);
        }
}

相关文章

  • Java8之Stream流(六)收集

    Java8之Stream流(一)基础体验 Java8之Stream流(二)关键知识点 Java8之Stream...

  • Java 8 Stream--开发手册

    什么是Java8 Stream,为什么需要Stream? Stream是Java8一大亮点,它与 java.io ...

  • Java8 学习笔记

    @(in action系列)[java8, lambda, stream] Java8 学习 java8 能高效的...

  • Stream流

    Stream流 java8新特性 Stream定义 A sequence of elements supporti...

  • java8 stream lambda

    记录Java8的stream操作,供自己复习。 创建Stream Employee类 创建stream方法 for...

  • JAVA8中Stream学习

    JAVA8中Stream学习 最近看了下Stream的api: Stream用户操作Collection族的数据,...

  • Java8 Stream 流的重用

    Java8 Stream 已经被操作或关闭 引言 在 java8 中,Stream 不能被重用,一旦它被使用或使用...

  • Java8 Stream 使用及其详解

    一、什么是Stream 二、Java7和Java8 聚合操作的区别。 三、Stream 总览 四、Stream 的...

  • Java 8 Stream 教程

    本文采用实例驱动的方式,对JAVA8的stream API进行一个深入的介绍。虽然JAVA8中的stream AP...

  • Java8新特性

    一、Lambda案例 案例1 案例2 二、Stream接口 Stream介绍 Stream在Java8中被定义为泛...

网友评论

      本文标题:Java8 Stream

      本文链接:https://www.haomeiwen.com/subject/izjiyftx.html