2016-12-01 200 views
2

我有一个对象Foo,其中包含一列Bar。这些类描述如下:Java 8 FlatMap - 以嵌套形式添加项目并使用FlatMap检索对象

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风格来做类似的事情?

回答

4

如果所有你要做的是打印Bar实例的名称,Foo和的整个构建和集合0个实例已过时。您可以生成并直接打印的名字:

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

您可以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,或者(在collect(Collectors.toList())第一结束)的操作拆分为2个Stream管道或使用peek(f->foos.add(f))Foo实例添加到foosList(这将需要您在运行之前实例化foosList管道)。

编辑:

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

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 
+0

我用你的答案以下编译错误:在类型IntStream的方法mapToObj(IntFunction )不适用的参数((我) - > {}) – KayV

+1

@KaranVerma现在全部修复。 – Eran

0

我也得到了以下使用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)); 
+1

不推荐使用'peek'。 – Holger

+0

peek有什么问题? – KayV

+2

它被明确声明为主要用于调试的函数。另请参见[“在Java流中只能查看调试?”](http://stackoverflow.com/q/33635717/2711488) – Holger