【问题标题】:Java 8 FlatMap - Add items in a nested form and retrieve object using FlatMapJava 8 FlatMap - 以嵌套形式添加项目并使用 FlatMap 检索对象
【发布时间】:2016-12-01 09:42:52
【问题描述】:

我有一个对象Foo,其中包含Bar 的列表。类描述如下:

class Foo {
    String name;
    List<Bar> bars = new ArrayList<Bar>();

    Foo(String name){
        this.name = name;
    }
}

class Bar {
    String name;

    Bar(String name){
        this.name = name;
    }
}

现在,我正在创建一个Foo 对象列表,每个对象都包含一个Bar 对象列表,如下所示:

IntStream
        .range(1, 4)
        .forEach(i -> foos.add(new Foo("Foo" + i)));

foos.forEach(f ->
            IntStream.range(1,4)
                    .forEach(i -> f.bars.add(new Bar("Bar"+i+" -> "+f.name))));

然后在Stream 上使用flatMap,如下所示:

foos.stream()
        .flatMap(f -> f.bars.stream())
        .forEach(i -> System.out.println("Bar Name : "+i.name));

如何使用 Java Stream 和 lambdas 在一次执行中完成所有这些事情?有没有其他方法可以用 Java 8 风格做这种事情?

【问题讨论】:

    标签: java java-8 java-stream collectors flatmap


    【解决方案1】:

    如果您要做的只是打印Bar 实例的名称,那么FooBar 实例的整个构造和集合已经过时。您可以直接生成和打印名称:

    IntStream.range(1, 4)
             .mapToObj(i -> "Foo" + i)
             .flatMap(name -> IntStream.range(1, 4)
                .mapToObj(i -> "Bar" + i + "->" + name))
             .forEach(System.out::println);
    

    【讨论】:

      【解决方案2】:

      您可以在mapToObj 而不是forEach 中生成Foo 实例:

      IntStream.range(1, 4)
               .mapToObj (i -> {Foo foo = new Foo("Foo" + i);
                                foo.bars =
                                    IntStream.range(1,4)
                                             .mapToObj(j -> new Bar("Bar"+j+" -> "+foo.name))
                                             .collect(Collectors.toList());
                                return foo;
                          })
               .flatMap (f -> f.bars.stream())
               .forEach(i -> System.out.println("Bar Name : "+i.name));
      

      但是,这不会将创建的 Foo 实例存储在 List 中。如果要将它们存储在 List 中,请将操作拆分为 2 个 Stream 管道(第一个以 collect(Collectors.toList()) 结尾)或使用 peek(f-&gt;foos.add(f))Foo 实例添加到 foos @987654333 @(这将要求您在运行管道之前实例化 foos List)。

      编辑:

      修正了一些错别字并测试了代码:

      Bar Name : Bar1 -> Foo1
      Bar Name : Bar2 -> Foo1
      Bar Name : Bar3 -> Foo1
      Bar Name : Bar1 -> Foo2
      Bar Name : Bar2 -> Foo2
      Bar Name : Bar3 -> Foo2
      Bar Name : Bar1 -> Foo3
      Bar Name : Bar2 -> Foo3
      Bar Name : Bar3 -> Foo3
      

      【讨论】:

      • 我使用您的回答得到以下编译错误: IntStream 类型中的方法 mapToObj(IntFunction extends U>) 不适用于参数 (( i) -> { })
      • @KaranVerma 现在一切都已修复。
      【解决方案3】:

      我还从使用 peek 和 mapToObject 的以下管道操作中获得了解决方案...

      IntStream.range(1, 4)
                  .mapToObj(i -> new Foo("Foo"+i))
                  .peek(f -> IntStream.range(1, 4)
                          .mapToObj(i -> new Bar("Bar"+i+"->"+f.name))
                          .forEach(f.bars::add))
                  .flatMap(f -> f.bars.stream())
                  .forEach(b -> System.out.println("Bar : "+b.name));
      

      【讨论】:

      猜你喜欢
      • 2017-04-02
      • 1970-01-01
      • 2018-06-02
      • 2021-11-25
      • 2020-08-22
      • 2019-07-07
      • 2015-03-04
      • 2023-01-15
      • 1970-01-01
      相关资源
      最近更新 更多