Java中のstream処理におけるmapとflatMapの比較と使用例


前言
Java 8の新特性Stream流式処理を使って、集合に対する操作効率を高めたり、lambada表式に合わせて、極致の簡略化コード、特に並列流というものがあります。いくつかの場合には効率を上げることができますし、符号化にも手間がかかりません。
そして、フロー処理の核心は浅いコピーと引用パイプであり、内部にはリードパイプのReferencePipelineが実現されています。彼は処理すべきデータの引用をコピーしてデータを処理し、最後に収集した結果もこれらの参照を別のセットに入れました。
今日はstream処理のmapとflatMapの二つの比較と使用について話します。
共通点と違い
まずソースコードを見てください。

  <R> Stream<R> map(Function<? super T, ? extends R> mapper);
   <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
共通点
  • は、すべてstreamに依存して変換され、lambandの入力値と戻り値とを結合して、1つのタイプをプログラム論理に従って別のタイプに変換します。
  • の最後の結果は、いずれもまた一つのストリームであり、これを継続的にストリーミング処理または収集することもできる。
  • 違います
  • 方法はパラメータが異なり、最初のパラメータは同じですが、2番目のパラメータはmapの2番目のパラメータには要求されませんでした。しかし、flatMapを使う場合は、2番目のパラメータはストリームでも受信します。
  • は、flatMapが複数のペア、すなわちmapが1つのデータストリームのうちの1つのデータノードを別のデータノードにマッピングし、flatMapは1つのデータストリームのうちの1つのデータノードを別のデータストリームにマッピングし、この他のデータストリームは1つのデータノードであってもよいし、複数のデータノードであってもよい。
  • flatmapは、単一変換でも複数組のマルチ変換でも良いので、flatmapはObservableに戻ることを要求しています。したがって、内部でfrom/justの再イベントを配布して、単一のオブジェクトを一つずつ取り出すことができます。
  • 使用例
    例えば、mapを使って一つのperオブジェクトを文字列オブジェクトにマッピングします。
    
      static class Per {
        public String name;
        public int age;
    
        public Per(String name, int age) {
          this.name = name;
          this.age = age;
        }
    
        public String getName() {
          return name;
        }
    
        public void setName(String name) {
          this.name = name;
        }
    
        public int getAge() {
          return age;
        }
    
        public void setAge(int age) {
          this.age = age;
        }
    
        @Override
        public String toString() {
          return "Per{" +
              "name='" + name + '\'' +
              ", age=" + age +
              '}';
        }
      }
    
      public static void main(String[] args) {
        List<Per> list = new ArrayList<>();
        list.add(new Per("listen", 22));
        list.add(new Per("bike", 24));
        list.add(new Per("milk", 27));
    
        List<String> collect = list.stream().map(Per::toString).collect(Collectors.toList());
    
        System.out.println(list);
        System.out.println("---");
        System.out.println(collect);
    
      }
    ペアが実現できるなら、私たちは必要です。もしper人が複数の子供を持っていると仮定して、この複数の子供を取得したいですが、mapを使って実現できますか?たとえば、下記のコードです。
    
      static class Child {
        public String name;
        public int age;
    
        public Child(String name, int age) {
          this.name = name;
          this.age = age;
        }
            @Override
        public String toString() {
          return "Child{" +
              "name='" + name + '\'' +
              ", age=" + age +
              '}';
        }
      }
    
      static class Per {
        public String name;
        public int age;
        public Child[] Children;
    
        public Per(String name, int age) {
          this.name = name;
          this.age = age;
        }
    
        public Child[] getChildren() {
          return Children;
        }
    
        public void setChildren(Child[] children) {
          Children = children;
        }
    
        public String getName() {
          return name;
        }
    
        public void setName(String name) {
          this.name = name;
        }
    
        public int getAge() {
          return age;
        }
    
        public void setAge(int age) {
          this.age = age;
        }
    
        @Override
        public String toString() {
          return "Per{" +
              "name='" + name + '\'' +
              ", age=" + age +
              '}';
        }
      }
    この時はこの子が多すぎて、私達が使っているのは配列保存です。今はまだmapを使っていますが、各perの子供配列しか受け入れられません。私たちが望む子供たちと一緒に受け入れられません。
    
      public static void main(String[] args) {
        List<Per> list = new ArrayList<>();
        Per per1 = new Per("Listen", 22);
        per1.setChildren(new Child[] {new Child("a", 1), new Child("b", 2)});
        Per per2 = new Per("Milk", 26);
        per2.setChildren(new Child[] {new Child("c", 1), new Child("d", 2)});
        list.add(per1);
        list.add(per2);
    
        List<Child[]> collect = list.stream().map(Per::getChildren).collect(Collectors.toList());
        collect.forEach(item -> System.out.println(Arrays.toString(item)));
      }
    flatMapを使うと実現できます。
    
      public static void main(String[] args) {
        List<Per> list = new ArrayList<>();
        Per per1 = new Per("Listen", 22);
        per1.setChildren(new Child[] {new Child("a", 1), new Child("b", 2)});
        Per per2 = new Per("Milk", 26);
        per2.setChildren(new Child[] {new Child("c", 1), new Child("d", 2)});
        list.add(per1);
        list.add(per2);
    
        List<Child> collect = list.stream().flatMap(item -> Arrays.stream(item.getChildren())).collect(Collectors.toList());
        System.out.println(collect);
    
      }
    以上、Java中のstream処理におけるmapとflatMapの比較と使用例についての記事をここに紹介しました。JavamapとflatMapの内容については、以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。