JAVA8学習 - 使用の観点から、深さ流フロー(学習処理)

ストリームの流れ

知人の流れ流れ

シンプルミートストリーム:公式の導入Streamクラス:

/**
 * A sequence of elements supporting sequential and parallel aggregate
 * operations.  The following example illustrates an aggregate operation using
 * {@link Stream} and {@link IntStream}:
 *
 * <pre>{@code
 *     int sum = widgets.stream()
 *                      .filter(w -> w.getColor() == RED)
 *                      .mapToInt(w -> w.getWeight())
 *                      .sum();
 * }</pre>
 * In this example, {@code widgets} is a {@code Collection<Widget>}.  We create
 * a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()},
 * filter it to produce a stream containing only the red widgets, and then
 * transform it into a stream of {@code int} values representing the weight of
 * each red widget. Then this stream is summed to produce a total weight.
 *
 */
 

そのようなケースを確認するために、JSと同様に操作をチェーン。流れを理解するためには、それがどのようなものであったかについてです。Linuxのようなパイプライン

ストリームは、3つの部分を含みます:

  1. ソース
  2. ゼロ以上の中間の操作
  3. 操作の終了

ストリーム分類操作:

  1. 遅延評価
  2. 先行評価
stream.xxx().yyy().zzz().count();

中級操作:遅延評価。のみ()が呼び出された回数、操作の途中では評価されます。

先行評価は、カウント数()メソッドは、直ちに先行評価と呼ばれる、評価さ呼び出されます。

先行評価の流れは一つだけとなります。

3つのストリームを生成します

public class StreamTest {
    public static void main(String[] args) {
        //本章才正式的开始对流进行讲解。

        //第一种方式,通过of方法
        Stream stream1 = Stream.of("hello","world");
        //第二种方式,通过数组方式
        String[] strings = new String[]{"hello","world"};
        Stream stream2 = Arrays.stream(strings);
        Stream stream3 = Stream.of(strings); //of的底层就是 通过Arrays.stream()来实现的.
        //第三种方式,通过集合.stream
        List<String> list = Arrays.asList("hello", "world");
        list.stream();

    }
}

ストリームを使用する方法(はじめに)

使用します。

public class streamTest2 {
    public static void main(String[] args) {
        //Intstream 怎么用
        IntStream.of(5, 6, 7).forEach(System.out::println);
        System.out.println("----");

        IntStream.range(3, 8).forEach(System.out::println);
        System.out.println("----");

        IntStream.rangeClosed(3, 8).forEach(System.out::println);
        System.out.println("----");
    }
}
public class streamTest3 {
    public static void main(String[] args) {
        //List类型,int的值, 对每一个元素*2,然后加起来,得到结果
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        //以前的写法
//        int i=0;
//        for (Integer i : list) {
//            sum += 2;
//        }
//        sum...

        //stream的写法,一行
        System.out.println(list.stream().map(integer -> integer*2).reduce(0,Integer::sum));

        //reduce方法,map()方法的调用会在下面进行详解.
        //实现简单,语义更明确
    }
}

)(削減、オペレーション、先行評価を終了します。

ディープストリームの流れ

関数型プログラミングでは、最も基本的なポイント:配達の方法は、以前のすべてのデータ転送の動作です。

  1. コレクションは、新しいストリーム()メソッドを提供します
  2. **ストリームは、導管の方法により取得した値を値を格納していません
  3. 機能的性質は、対流結果を生成するが、基礎となるデータソースを変更しない、データセットは、基礎となるソース・ストリームとして使用することができます
  4. 遅延検索、多くの動作フロー(濾過、マッピング、ソートなど)の遅延(遅延)を実現することができます

この例を見てください:

public class streamTest4 {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("hello", "world", "hello world");
      //lambda写法   
      //stream.toArray(length -> new String[length]);
      //方法引用的写法 (构造方法引用)
        String[] stringArray = stream.toArray(String[]::new);
        Arrays.asList(stringArray).forEach(System.out::println);
    }
}

既知の流れ、ターン一覧

        //已知流,转List
        Stream<String> stream = Stream.of("hello", "world", "hello world");
        List<String> collect = stream.collect(Collectors.toList());
        collect.forEach(System.out::println);

コレクト()メソッドは、詳細 - コレクターをも内部を収集(三つのパラメータ)メソッドは、これを達成するため

    /**
     * 第一个参数介绍
     * Performs a <a href="package-summary.html#MutableReduction">mutable
     * reduction</a> operation on the elements of this stream.  A mutable
     * reduction is one in which the reduced value is a mutable result container,
     * such as an {@code ArrayList}, and elements are incorporated by updating
     * the state of the result rather than by replacing the result.  This
     * produces a result equivalent to:  第二个参数的介绍
     * <pre>{@code
     *     R result = supplier.get();
     *     for (T element : this stream)
     *         accumulator.accept(result, element);
     *     return result;
     * }</pre>
     * 被并行化. 流带来的好处.
     * <p>Like {@link #reduce(Object, BinaryOperator)}, {@code collect} operations
     * can be parallelized without requiring additional synchronization.
     * 这是一个终止操作.
     * <p>This is a <a href="package-summary.html#StreamOps">terminal
     * operation</a>.
     * 方法签名是非常适合于使用方法引用的方式.就是最下面举例的Example
     * @apiNote There are many existing classes in the JDK whose signatures are
     * well-suited for use with method references as arguments to {@code collect()}.
     * For example, the following will accumulate strings into an {@code ArrayList}:
     * <pre>{@code
     *     List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add,
     *                                                ArrayList::addAll);
     * }</pre>
     * 扩展功能:字符串实现拼接的操作
     * <p>The following will take a stream of strings and concatenates them into a
     * single string:
     * <pre>{@code
     *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
     *                                          StringBuilder::append)
     *                                 .toString();
     * }</pre>
     *
     * @param <R> type of the result
     第一个参数:结果容器,如LinkList
     * @param supplier a function that creates a new result container. For a
     *                 parallel execution, this function may be called
     *                 multiple times and must return a fresh value each time.
     第二个参数:关联性的,不冲突的,无状态的,用于合并.   item->list
     * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
     *                    <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                    <a href="package-summary.html#Statelessness">stateless</a>
     *                    function for incorporating an additional element into a result
     第三个参数:用于融合,将上次遍历得到的集合融合到最终的结果集中.
     * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
     *                    <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                    <a href="package-summary.html#Statelessness">stateless</a>
     *                    function for combining two values, which must be
     *                    compatible with the accumulator function
     * @return the result of the reduction
     */
    <R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);

ソースによって説明:我々は、基礎となる転送リストを達成するために、このコレクト3パラメータ法によってであることを認識し、我々はこれら三つのパラメータを知るために一つずつ来ます。

1.パラメータ1:供給、機能サプライヤインタフェース機能の種類:予備コンテナリストを提供すること

2.パラメータ2:アキュムレータ、インターフェース機能BiConsumerのタイプの機能:アキュムレータは、ストリームは、収集要素に蓄積されています。

3.パラメータ3:合成、インターフェース機能BiConsumerのタイプの機能:合成、最終リストに融合された結果として生じるトラバーサルの最後のセット。

自分の文書上記のコレクターに読んでください。私は、これらの要素がそれに反映されていると言います。

上記の理解を通じて、我々は次のように、底部流のリストを達成するために彼の変換を実現するために、三つのパラメータ()メソッドを収集することができます。

//功能描述:已知流,转List
Stream<String> stream = Stream.of("hello", "world", "hello world");
List<String> collect = stream.collect(Collectors.toList());
collect.forEach(System.out::println);

//使用collect(三个参数)的底层方法来实现这个操作.  因为这个三参的collect()方法就是这个操作的底层.
List<String> list = stream.collect(() -> new ArrayList(),(theList,item)->theList.add(item),(theList1,theList2)->theList1.addAll(theList2));

//通过方法引用优化后的代码如下:
//优化后的代码:
List<String> list1 = stream.collect(LinkedList::new,LinkedList::add,LinkedList::addAll);

文字列連結操作の上方に設けられた注さらにソース


     * 扩展功能:字符串实现拼接的操作
     * <p>The following will take a stream of strings and concatenates them into a
     * single string:
     * <pre>{@code
     *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
     *                                          StringBuilder::append)
     *                                 .toString();
     * }</pre>
     *

その他の使用の流れ

        //使用 Collectors.toCollection()方法来实现 流转List
        Stream<String> stream = Stream.of("hello", "world", "hello world");
//        ArrayList<String> list = stream.collect(Collectors.toCollection(ArrayList::new));
//        list.forEach(System.out::println);

        //使用 Collectors.toCollection()方法来实现 流转Set
        Set<String> list = stream.collect(Collectors.toCollection(TreeSet::new));
        list.forEach(System.out::println);

        //使用 方法来实现,流转String字符串
        stream.collect(Collectors.joining());

その後、これらの変換を達成するために提供されるこれらのストリームJAVA8。実際の開発で使用を使用できるかどうか、より多くの配慮、リスト、セットを与えるために、時間を開発しました。

再考

public class StreamTest5 {
    public static void main(String[] args) {
        //集合,全部转换大写,然后输出.
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //要考虑能不能用函数式接口,lambda表达式的技能?显然是可以呢
        //这是不是映射? 先要要用map. 给定一个参数,返回一个结果.
        //java8提供这些接口,就是为了方便开发者.合理的应用.
        list.stream().map(String::toUpperCase).collect(Collectors.toList()).forEach(System.out::println);
      
        //求出每个数字的平方,然后打印出来
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
        list1.stream().map(item -> item * item).collect(Collectors.toList()).forEach(System.out::println);
      
    }
}
        //要考虑能不能用函数式接口,lambda表达式的技能?显然是可以呢
    //这是不是映射? 先要要用map. 给定一个参数,返回一个结果.
    //java8提供这些接口,就是为了方便开发者.合理的应用.

flatMap()メソッド:フラットマッピング


    /**
     * Returns a stream consisting of the results of replacing each element of
     * this stream with the contents of a mapped stream produced by applying
     * the provided mapping function to each element.  Each mapped stream is
     * {@link java.util.stream.BaseStream#close() closed} after its contents
     * have been placed into this stream.  (If a mapped stream is {@code null}
     * an empty stream is used, instead.)
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @apiNote
     * The {@code flatMap()} operation has the effect of applying a one-to-many
     * transformation to the elements of the stream, and then flattening the
     * resulting elements into a new stream.
     *
     * <p><b>Examples.</b>
     *
     * <p>If {@code orders} is a stream of purchase orders, and each purchase
     * order contains a collection of line items, then the following produces a
     * stream containing all the line items in all the orders:
     * <pre>{@code
     *     orders.flatMap(order -> order.getLineItems().stream())...
     * }</pre>
     *
     * <p>If {@code path} is the path to a file, then the following produces a
     * stream of the {@code words} contained in that file:
     * <pre>{@code
     *     Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8);
     *     Stream<String> words = lines.flatMap(line -> Stream.of(line.split(" +")));
     * }</pre>
     * The {@code mapper} function passed to {@code flatMap} splits a line,
     * using a simple regular expression, into an array of words, and then
     * creates a stream of words from that array.
     *
     * @param <R> The element type of the new stream
     * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *               <a href="package-summary.html#Statelessness">stateless</a>
     *               function to apply to each element which produces a stream
     *               of new values
     * @return the new stream
     */
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

そして、マップのような多くの、しかし全く違うそうでない場合は、移動するための方法は存在しないでしょう。

地図を平坦化。

1.mapがマッピングされたときに、3リスト、リストの集合はそれぞれ異なる値を有する。マッピングモジュールが完了した後も

2.flatMapがマッピングされた場合は、3リストのコレクションは、リストへの収束を結びつけるために行きます。

例例:

//每一个元素都乘方,然后将数据作为一个整体,输出. 当做一个集合.  就要用flatmap()
        Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
        listStream.flatMap(theList->theList.stream()).map(integer -> integer*integer).forEach(System.out::println);

他の方法は、Streamクラスに記述しました

  1. 生む()
    /**
     * Returns an infinite sequential unordered stream where each element is
     * generated by the provided {@code Supplier}.  This is suitable for
     * generating constant streams, streams of random elements, etc.
     *
     * @param <T> the type of stream elements
     * @param s the {@code Supplier} of generated elements
     * @return a new infinite sequential unordered {@code Stream}
     */
    public static<T> Stream<T> generate(Supplier<T> s) {
        Objects.requireNonNull(s);
        return StreamSupport.stream(
                new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
    }

以下の例の使用方法?:

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
        System.out.println(generate.findFirst());
    }
}
Optional<T> findFirst();

この関数は、FindFirst()メソッドは、オプションを返すのはなぜですか?

オプションなので、NPEは、問題を回避することです。

だからここOptional.ifPresentを()を使用する必要があり、これは次のように任意のクラスの適切な使用を改正する必要があります:

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
       generate.findFirst().ifPresent(System.out::println);
    }
}
  1. 反復()
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
        Objects.requireNonNull(f);
        final Iterator<T> iterator = new Iterator<T>() {
            @SuppressWarnings("unchecked")
            T t = (T) Streams.NONE;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                return t = (t == Streams.NONE) ? seed : f.apply(t);
            }
        };
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                iterator,
                Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
    }

どのように使用するには?

package com.dawa.jdk8.stream;

import java.util.UUID;
import java.util.stream.Stream;

public class StreamTest6 {
    public static void main(String[] args) {
        Stream<String> generate = Stream.generate(UUID.randomUUID()::toString);
       generate.findFirst().ifPresent(System.out::println);

        //如果不加限制,iterate 会变成一个无限流.
        //Stream.iterate(1, integer -> integer + 2).forEach(System.out::println);
        //所以在使用的时候一定不要单独使用.
        //要搭配limit()方法,一个中间操作,使用.
        Stream.iterate(1, integer -> integer + 2).limit(6).forEach(System.out::println);
    }
}

注:チェックしない場合//、反復は無限のストリームになります。
//だから、単独で使用するときに使用しないことを確認してください。
//上限に一致するように()メソッド、中間の操作および使用。

フロー要素2よりも大きい(1,3,5,7,9)を見つけ、その後、乗算各要素2、次いで第2のエレメンタリストリームでは無視され、その後、最終的には最初の2つの基本ストリームを削除し、そしてフロー要素の総和を求めます。

//找出(1,3,5,7,9)流中大于2的元素,然后将每个元素乘以2,然后忽略流中的前两个元素,然后再取出流的前两个元素,最后求出流中元素的总和.
// Stream<Integer> stream = Stream.of(1, 3, 5, 7, 9);
        Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);//通过iterate方法来获取值
        System.out.println(stream.filter(integer -> integer > 2).mapToInt(integer -> integer * 2).skip(2).limit(2).sum());
//用到的方法. map,mapToint,skip,limit.
  1. ...スキップ)(スキップ

  2. ...リミット()インターセプション

  3. ...マップ()。mapToInt()、mapToDouble()....映射

    mapToIntは...自動ボクシングと自動的にアンボクシングを避ける。(回避性能の損失)。

  4. ...合計()、分()、MAX()。最大値、最小値、合計値、等

    合計は()int型の戻り値です。

    。MIN()MAX()、戻り値の型がある:OptionalInt。

    なぜ?任意のクラス、ために使用するかどうかは、空にすることはできません。この値の性質に依存します。

  5. summaryStatistics():概要、ストリームの簡単な要約統計。

    例えば:要約オブジェクト:IntSummaryStatistics {平均数= 2、和= 32、分= 14、= 16.000000、最大= 18}

    このクラスは、さまざまな方法を提供します。

    getCount
    getSum
    getMin
    getMax
    getAverage
    toString

上記の場合は、それがすでに必要な場合は、。メソッドの数Streamクラスを使用して、彼らの公式のソースを確認しました。

注:中間ストリームを操作すると、操作の終了時であることを新しいストリームを返し、最終的な結果を取得します。

ストリームについて、閉じた問題です。

画像-20200104174241664

ちょうど不注意間の動作では、このような例外がプロンプトストリームにスローされたとき、それは閉じられています。

下記のリプレイコード:


Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);
System.out.println(stream);
System.out.println(stream.filter(integer -> integer > 2));
System.out.println(stream.distinct());

特長・ストリーム

  1. それが動作したら。クローズ回数が自動的に流れ。
  2. ストリームで繰り返すことはできません。
  3. 流れを閉じて動作を継続することはできません。
  4. 各中間操作は、新たなストリームオブジェクトの操作を返します。

避けるためにどのように?

  1. 氏は、ストリームの中に、操作を完了し、そして後のストリームを生成します。

  2. そして、新しく生成されたストリームが動作します。

  3. Stream<Integer> stream = Stream.iterate(1, integer -> integer + 2).limit(6);//通过iterate方法来获取值
    
    System.out.println(stream);
    Stream<Integer> stream1 = stream.filter(integer -> integer > 2);
    System.out.println(stream1);
    Stream<Integer> stream2 = stream1.distinct();
    System.out.println(stream2);

終了操作と中間操作上の本質的な違い

例:

public class StreamTest7 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //首字母大写,其他的小写,然后打印输出.
        list.stream().map(item -> item.substring(0, 1).toUpperCase() + item.substring(1)).forEach(System.out::println);

        //另外的操作
        list.stream().map(item -> {
            String result = item.substring(0, 1).toUpperCase() + item.substring(1);
            System.out.println("test");
            return result;
        });//运行之后没有值

        //另外的操作
        list.stream().map(item -> {
            String result = item.substring(0, 1).toUpperCase() + item.substring(1);
            System.out.println("test");
            return result;
        }).forEach(System.out::println);//运行之后能够执行.

        //原因:中间操作,如果没有终止操作,是不会自己执行的,是lazy类型的.是惰性求值的.

    }
}

原因:なし終了操作が自分の行っていないされていない場合は、中間運転、それは怠惰な遅延評価のタイプです。

そして、効率の問題を検討します。

おそらく、多くの中間の操作を考えるかもしれない何回もリサイクルされます、それは効率が低下します。

実際には、それは一度だけ行われ、効率に影響を与えません。

一緒にコンテナ、すべての中間の操作があります。動作の一の実行は、冗長性を持っていません。

中間操作および終了操作を区別する方法

中間動作は、例えば、ストリームを返し、ストリームオブジェクトを返します 、...など

終了操作との中間の動作への影響:別の操作を見て

public class StreamTest8 {
    public static void main(String[] args) {
        IntStream.iterate(0, i -> (i + 1) % 2).distinct().limit(6).forEach(System.out::println);
    }
}

上記のコードの後に​​自動的に終了するまで実行されていません。

これは次のように修正する必要があります。

public class StreamTest8 {
    public static void main(String[] args) {
        IntStream.iterate(0, i -> (i + 1) % 2).limit(6).distinct().forEach(System.out::println);
    }
}

その理由は、インパクトの動作の動作および終了のために中央です。

  1. 最初の実行制限した場合、終了操作である。そして、プログラムは終了する繰り返しを排除します。

  2. 操作を排除することの最初の繰り返しが最初のケース、リターン流れ、その後、6を取っている場合、それは流れをオフにしません。


ストリームの下の深さ

  • 別の違いはことイテレータ、ストリームの並列動作、専用型イテレータコマンド、連続操作であります
  • シリアルモードでトラバースし、次の項目を読み取るために各項目を読み取るとき。
  • パラレルデータをトラバースするために使用されるとき、それは、それぞれの前記複数のセグメントに分割され、異なるスレッド、プロセス、およびその後の結果を出力します
  • JAVA7に導入並列運転依存ストリームstreamをFORK /フレームに参加します。

本質的に3つの主な操作は、フロー:ソース - >中間操作 - >中間操作 - > ...->終了操作

ここでは、学習へのSQLリファレンスを使用します

select name from student where age>20 and address='beijing' order by age desc;

記述言語

ストリームでは、このSQLを記述

student.stream()
  .filter(student->student.getAge>20)
  .filter(student->student.getAddress()
          .equals("beijing")
          .sorted(...)
          .forEach(student->System.out.println(student.getName()));
//这个描述和上面的SQL其实是等价的.

あなただけのように降順でルールに従ってスクリーニングすることが、その後DBにコマンドを送信ではなく、あなただけの説明を与えることを見つける方法、および全体のプロセスのために、あなたは根本的に達成する方法を教えてくれませんでした。

SQLも、ストリームの場合である。ただ、記述言語。

この方法では、内部反復と呼ばれています。

内部の反復

外部反復(道の前に)

  1. 治療は貧しい読みやすさに比べて、完全な実装の古いバージョンに基づいて、記述的ではありません。そして、記述言語。

  2. 操作は、直列並列化されていません

for(int i=0;i<student.size();i++){
  Student student = students.get(i);
  if(student.getAge()>20&&student.getAddress().equals("beijing")){
    list.add(student);
  }
}
//然后进行排序
Collection.sort(list,Comparator()...);
//然后再去寻找需要的东西
for(Student student:list){
    System.out.println(student.getName);
}

内部反復(記述言語)

カップルはまた、それを読むことができます。

student.stream()
  .filter(student->student.getAge>20)
  .filter(student->student.getAddress()
          .equals("beijing")
          .sorted(...)
          .forEach(student->System.out.println(student.getName()));

ストリーム出現とコレクションが密接にリンクされています。

  1. 動作並行して実行されてもよいです。
  2. ときに根本的な実行ではなく、ループスルーを調整するための条件

内部および外部のほとんどの反復の反復性の違い

  1. カップリング
  2. ボトム治療
  3. 様々なパラレルおよびシリアルの

概要

  1. データ収集は、データストア自体に関するものです。
  2. 関心の流れは、計算されたデータです。
  3. ストリームは、同様のポイントがあるイテレータ:フローを再利用し、消費することはできません。
  4. 下を使用してください:フォーク/ joinメソッドを実行するために小さなタスクに大きなタスクを分解する。

注意が必要なほとんどの

流れの原則の実装は間違いなく実行サイクルメソッドトラバーサルの方法ではありません。


パラレルフローで使用される(parallelStream)

シリアルストリーム(ストリーム())と決意効率の並列ストリーム(parallelStream())。

  • シリアルストリーム
package com.dawa.jdk8.stream;

import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class StreamTest9 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>(5000000);
        for (int i = 0; i < 5000000; i++) {
            list.add(UUID.randomUUID().toString());
        }

        System.out.println("开始排序");
        long startTime = System.nanoTime();//纳秒 比毫秒的精度高
        list.stream().sorted().count();

        long endTime = System.nanoTime(); //纳秒, 结束时间

        long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("耗时:" + millis + "毫秒");
    }
}

実行結果:シリアル時間:4.0秒

画像-20200104185911432

  • パラレルフロー
public class StreamTest9 {
    public static void main(String[] args) {
        ArrayList<Object> list = new ArrayList<>(5000000);
        for (int i = 0; i < 5000000; i++) {
            list.add(UUID.randomUUID().toString());
        }

        System.out.println("开始排序");
        long startTime = System.nanoTime();//纳秒 比毫秒的精度高
        list.parallelStream().sorted().count();

        long endTime = System.nanoTime(); //纳秒, 结束时间

        long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
        System.out.println("耗时:" + millis + "毫秒");
    }
}

結果:並列時間:1.1秒

画像-20200104185700662

パラレルおよびシリアル - コストの時差:3-5回。

短絡

public class StreamTest10 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world", "hello world");
        //找出列表中,长度为5的第一个单词,同时将长度5打印出来.
//        list.stream().mapToInt( String::length).filter(length -> length == 5).findFirst().ifPresent(System.out::println);

        list.stream().mapToInt(item -> {
            int length = item.length();
            System.out.println(item);
            return length;
        }).filter(length -> length == 5).findFirst().ifPresent(System.out::println);

    }
}

結果は設定します:

画像-20200104190933025

一つだけ印刷されたときに、なぜ印刷?

理由:容器の操作ごとに記憶されている容器。

ストリームは、反復プロセスである場合、容器はこの使用の値に動作一つ一つを保持します

ルールをフィルタリングしていない場合は、起こるのだろう短絡算術演算を。これが第二の理由である。ただ、資格を見つけ、実行に戻っていないだろう。

以下のような:ルールが完全に実装されます満たしていない場合には、以下の結果を完了します。

画像-20200104191315339

ケース:(アプリケーションflatMap方法)すべての単語の集合を見つけ、重い行きます。

public class StreamTest11 {
    public static void main(String[] args) {

        //找出集合中所有的单词,并去重.
        List<String> list = Arrays.asList("hello world", "hello welcome", "hello", "hello world hello", "hello world welcome");
        //要输出: hello world welcome.
//        list.stream().map(item -> item.split(" ")).distinct().collect(Collectors.toList()); //不对
        List<String> collect = list.stream().map(item -> item.split(" ")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
        collect.forEach(System.out::println);
    }
}

ケース:こんにちは、組み合わせた二組 - 名(flatMapアプリケーション)

public class StreamTest12 {
    public static void main(String[] args) {
        //将两个集合组合起来,  打招呼-人名
        List<String> list1 = Arrays.asList("Hi", "Hello", "你好");
        List<String> list2 = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu");

//        list1.stream().map(item->item.concat(list2.stream().map()))
        List<String> collect = list1.stream().flatMap(item -> list2.stream().map(item2 ->item+ " " + item2)).collect(Collectors.toList());
        collect.forEach(System.out::println);
    }
}

グループ化とパーティション

SQLでグループとして。

select * from studeny group by name;

結果:地図<文字列、リストを >

アイデアの伝統的な実現:

  1. 循環リスト
  2. 生徒の名前を削除します
  3. 名前マップの存在を確認し、何の直接マップに存在追加されません。マップを取り出しListオブジェクトに存在すること、そして学生のリストにオブジェクトを追加します。
  4. Mapオブジェクトが返さ

パケットフローは、により達成される(groupingby()メソッド)


public class StreamTest13 {
    public static void main(String[] args) {
        Student student1 = new Student("zhangsan", 100, 20);
        Student student2 = new Student("lisi", 90, 20);
        Student student3 = new Student("wangwu", 90, 30);
        Student student4 = new Student("zhaoliu", 80, 40);

        List<Student> students = Arrays.asList(student1, student2, student3, student4);

        //Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getName));
       // System.out.println(collect);
        Map<Integer, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getScore));
        System.out.println(collect);
    }
}

流れと、このSQLを達成するためにどのように?

select name,count(*) from student group by name; 

それはに簡単です:

Map<String, Long> collect = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
        System.out.println(collect);

グループ名を達成し、グループフローを使用してどのように平均以上を取るために?

Map<String, Double> collect = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.averagingDouble(Student::getScore)));
        System.out.println(collect);

上に書いたが、グループ化の概念です。

グループ:グループによる

ゾーニング:によってパーティション

パーティション

パーティションは、ブール値として、パケットの特別な場合であり、このようなカットオフ点90のようにのみtrueとfalse。上記の場合は、パーティションに分割されています

        Map<Boolean, List<Student>> collect = students.stream().collect(Collectors.partitioningBy(student -> student.getScore() > 90));
        System.out.println(collect);
collect.get(true);//获取ture对应的值
collect.get(false);//获取false对应的值

おすすめ

転載: www.cnblogs.com/bigbaby/p/12150703.html