JDK 8の強力なStream

9109 ワード

JDK 8の中で強大なStream
2013年に発表されたJDK 8は、まさに浸透していると言えます
今日この文章は主にJDK 8の中の新しい特性を討論します
Stream
Streamの紹介
  • Streamは「ストリーム」と訳されるが、彼はioストリームのような伝送ストリームではなく、コレクションオブジェクト機能の強化であり、コレクションおよび配列処理のいくつかの「S」動作
  • を含む.
  • さらにStreamは並列操作を含む制御が適切であればプログラム効率が大幅に向上する
  • .
  • 人はJDKが8代目(あるいはもう少し早い)から徐々に研究を始めてGoogleGuavaやHutoolなど昔から風采のあるライブラリの中のコードを実現しているような気がします.もちろんjavaとCの関係は言うまでもありません.ハハハ(冗談)
  • Streamの基本使用
    ここでは、よく使われる操作をできるだけ効果的に説明します.
    (スイカを抱えてからゴマ拾いをしましょう)
  • Streamの作成
  • Stream.of(...);(静的メソッドによる有限長の作成)
  • Collection.stream()(コレクション内の作成方法)はシリアルストリーム
  • を返します.
  • Collection.parallelStream()はパラレルストリームを返します
  • 並列操作は開発ニーズに応じて使用できる効果が比較的に明らかである
  • .
  • Arrays.stream(配列参照)
  • //  Stream    of
    Stream.of(1,2,3,"a","b","c");
    //    
    var list=new ArrayList();
    list.stream();
    //    (    int[] double[] long[])
    int[] int={1,2,3,4,5};
    Arrays.stream(int);
  • Streamの操作手順
  • Intermediate(中級操作)は、複数回の操作
  • を実行することができる.
  • Terminal(究極の操作)1回の操作のみを実行するために必要な操作
  • Short-circuiting(短絡動作)は1回の
  • しか実行できない.

    Streamのミッドレンジ操作(Intermediate)
    Stream内の要素のフィルタ順序付けなどを複数回行うことができます
    ミッドレンジオペレーションは多層処理が可能であるが、ミッドレンジオペレーションが1回遍歴するわけではない
    変換操作はlazy(不活性評価)であり,Terminal操作が実行された場合にのみ一度に実行されると考えられる.
  • filterは、Streamに対して条件付きフィルタを指定し、filterが入力したLambda式はPredicateインスタンスでなければならない.パラメータは任意のタイプであり、その戻り値はbooleanタイプでなければならない.
  • class Stu{
        private String name;
        private int age;
        private double money;
        ...
    }
    var list=List.of(
                new Stu("Asen",18,100.0),
                new Stu("Bsen",28,2000.0),
                new Stu("Csen",38,3000.0)
            );
            //         Stu    18      
    list.stream().filter(s->s.getAge()==18).forEach(out::println);
            //                  
  • distinct stream中の要素の重量を調べる
  • int[] i={1,2,3,4,5,2,3,4};
    //            
    Arrays.stream(i).distinct().forEach(out::println);
    //1,5
  • mapにはmapToDouble,mapToInt,mapToLongの3つの変形、すなわちStream中のデータを処理または変換するタイプ
  • がある.
    int[] i={1,2,3,4,5,2,3,4};
    //        *10
    Arrays.stream(i).distinct()
          .map(i->i*10).forEach(out::println);
    //10,50
    //         double  
    Arrays.stream(i).distinct()
          .mapToDouble(i->i).forEach(out::println);
    //1.0,5.0
  • flatMapによって入力されるLambda式は、Functionインスタンスパラメータが任意のタイプである必要があり、その戻り値タイプはStream
  • である必要があります.
    Stream.of(1,1,1,1)
          .flatMap(v->Stream.of(v*10)).forEach(out::println);
    //10 10 10 10
  • concatは2つのStreamをつなぎ合わせる1つのStreamが並列であれば、新しいStreamも並列の
  • である.
    Stream.concat(Stream.of(1,2,3),Stream.of(4,5))
          .forEach(out::println);
    //     
    // 1  2  3  4  5  
  • skipエレメントの最初のエレメント
  • を削除
  • peekは、Stream内のすべての要素を含む新しいStreamを作成し、
  • を先に実行する新しい消費関数を提供することもできます.
    Stream.of(1, 2, 3, 4, 5)
          .skip(3)
          .peek(integer -> out.println("accept:" + integer))
          .forEach(out::println);
    //  accept:4
    //  4
    //  accept:5
    //  5
  • sorted要素を並べ替えるリロードメソッドは、Integer::compareTo
  • などの指定ルールを入力する必要があります.
    Stream.of(1, 3, 4, 2, 5)
          .sorted()
          .forEach(out::println);
          //1 2 3 4 5
    Stream.of(1, 3, 4, 2, 5)
          .sorted(Comparator.reverseOrder())
          .forEach(out::println);
          //5 4 3 2 1

    Streamの端末操作(Terminal)
    端末操作は、一度に値を戻したり出力したりすることしかできません
    また、Streamを二次的に利用することはできません.例えば、二次印刷二次変換
  • forEachOrdered forEachの前にずっと使用していた端末操作ではない結果が見えない前者は要素挿入順で遍歴後者はStreamが順を指定すると指定順
  • である.
  • countは要素の個数
  • を返す.
    vat int=Stream.of(1,2,3,4).count();
    //int = 4
  • max min指定されたComparatorに従って最大値または最小値を検索すると、Streamの最小要素の2つの値がStreamの最小値であるOptionalが返されます.したがって、maxは最小値minを見つけることもできるし、最大値
  • を見つけることもできます.
    var list=List.of(1,2,3,2,4);
    var max=list.stream().max((o1,o2)->o2-o1);
    // max           o=1
    var min=list.stream().min((o1,o2)->o1-o2);
    // min        
  • データの簡単な処理:
  • //   ,sumValue = 10,     
    int sumValue = Stream.of(1, 2, 3,4).reduce(0,Integer::sum);
    //   ,sumValue = 10,     
    sumValue = Stream.of(1, 2, 3,4).reduce(Integer::sum).get();
    //     ,minValue = -3.0
    double minValue = Stream.of(-1.5, 1.0,-3.0,-2.0)
    .reduce(Double.MAX_VALUE, Double::min);
  • collectは端末操作であると同時に、Stream中の要素生成集合栗のようなハイエンド操作であると考えられる:
  • List toList
  • を生成する.
    var tolist=Stream.of(2,1,3,2,4,3)
                     .distinct()
                     .sorted()
                     .collect(Collectors.toList());
    out.println(tolist);//    [1, 2, 3, 4]
       ArrayList
  • setヘッダtoSet
  • を生成する
    var toset=Stream.of("a","b","c","2")
                    .distinct()
                    .sorted()
                    .collect(Collectors.toSet());
    out.println(toset);//[a, 2, b, c]
       HashSet
  • 生成集合タイプを指定するにはtoCollection
  • を使用します.
    var collectors=Stream.of(1,2,3,4,5)
        .collect(Collectors.toCollection(ArrayList::new));
  • 生成map対map集合の生成は複雑であり、変換時に正常なmapのように使用できない問題があることが分かるが、
  • を解決することができる.
    Student[] stu= {new Student("Asen", 02, 10000),
                    new Student("Byin", 01, 2000),
                    new Student("Dfei", 03, 2000),
                    new Student("Cjie", 03, 300)};
    //    ID    name    
    //      map     ID=03         
    //    toMap       
    var stumap=Arrays.stream(stu)
                     .sorted(comparing(Student::id))
                     .collect(Collectors.toMap(Student::id, Student::name));
    //                     
  • toMapの大きな穴の1つ:同じ値がある場合は異常解決策を放出します:
  • Student[] stu= {new Student("Asen", 02, 10000),
                    new Student("Byin", 01, 2000),
                    new Student("Dfei", 03, 2000),
                    new Student("Cjie", 03, 300)};
    //                    
    var stumap=Arrays.stream(stu)
                     .sorted(comparing(Student::id))
                     .collect(Collectors.toMap(Student::id, Student::name,(x,l)->l));
    //              null                   
  • toMapの大きな穴の2:nullの値でも異常解決策が投げ出されます:
  • var nullmap=Arrays.stream(stu)
    .sorted(comparing(Student::id))
    .collect(Collectors
                .toMap(Student::id, s-> s.name()==null?"":s.name(),(l,x)->x));
    //             null        
  • Collectors.joining Streamを文字列
  • に変換
    //         
    Stream.of("1","2","3","4").collect(Collectors.joining(","));
    //        
    list.stream().map(r -> r.toString()).collect(Collectors.joining(","));
    ps:                             

    Streamのショート操作Short-circuiting
  • allMatchは、ブレークストリームの要素がすべて指定条件を満たすかどうかを判断します.すべてが条件を満たす場合はtrueを返します.そうでない場合はfalse
  • を返します.
    boolean allMatch=Stream.of(1,2,3,4,5)
                           .allMatch(i->i>0);
    // allMatch=true
  • anyMatchは、要素のうち少なくとも1つが条件を満たすか否かを判断し、1つがtrueを返すすべてが満たされなければfalse
  • を返す.
    boolean anyMatch=Stream.of(1,2,3,4,5)
                           .allMatch(i->i<0);
    // anyMatch=false
  • noneMatchは、Stream中の要素がすべて指定条件を満たすか否かを判定し、戻りtrueを満たさないか否かを判定し、逆にfalse
  • を返す.
    boolean noneMatch=Stream.of(1,2,3,4,5)
                           .noneMatch(i->i<0);
    // noneMatch=true
  • limit指定個数の要素をStreamから切り取るStream要素の個数が指定個数より小さい場合、
  • をすべて返す.
    Stream.of(1,2,3,4,5)
          .limit(3).forEach(out::println);
    // 1,2,3

    Stream拡張操作
    Streamの一般的な操作についてはここまでです
    ちょっと高級な'sao'操作についてお話しします
  • 問題1を見てください:1つの文字列に対してその中の英語のアルファベットの個数を選ぶことを要求します普通の方式私達は具体的な説明をしません
  • //                                                       
    String st="12asbs*346";
    var vi=toList(convert(char[].class,st)).parallelStream()
            .flatMap(vv->Stream.of((char)vv))
            .filter(ss->ss>='A'&&ss<='Z'||ss>='a'&&ss<='z').count();
    // vi=4
    //                            
    //ps                      
  • 問題2を見てください:Streamの中の要素に対して奇数の偶数のグループに従うことを要求しますもちろんみんなは実際の応用の中で配列の文字列の操作を結合することができます
  • 補足partitioningBy戻りmap集合データパケットはBooleanに従ってのみパケット化できる、すなわちpartitioningByが入力するlambda式はBooleanタイプ
  • を返すのみである.
    var map=Stream.of(1,2,3,4,5)
                  .collect(Collectors.partitioningBy(it->it%2==0));
    //{false=[1, 3, 5], true=[2, 4]}
    var map3=Stream.of(1,2,3,4,5)
                    .collect(Collectors.partitioningBy(it->it%2==0,Collectors.counting()));
    //{false=3, true=2}
  • 请看题3:要求对Stream中元素统计每元素出现的个数娟姐的小弟子们们你们想到什么啊--ハハハハ
  • 補足groupingBy戻りmapもデータパケットに属するが任意のタイプでパケット
  • を行う.
    var map=Stream.of("1","2","a","a","3","b","2")
                    .sorted()
                    .collect(Collectors.groupingBy(ic->ic,Collectors.counting()));
    map.forEach((k,v)->out.println(k+"     "+v));
    /*1     1
    2     2
    3     1
    a     2
    b     1*/
    ps: