2016-12-01 38 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