2015-10-05 66 views
3

考慮下面的例子,我想這對列表進行排序,並嵌套列表的Java 8流 - 排序嵌套列表層次

class Foo { 
    public int sort; 
    public List<Bar> bars; 
    public Foo(int sort) { 
     this.sort = sort; 
    } 

} 

class Bar { 
    public int sort; 

    public Bar(int sort) { 
     this.sort = sort; 
    } 
} 

@Test 
public void testSortering() { 
    Foo foo = new Foo(1); 
    Foo foo2 = new Foo(2); 
    Bar bar = new Bar(1); 
    Bar bar2 = new Bar(2); 
    foo.bars = Arrays.asList(bar2, bar); 
    foo2.bars = Arrays.asList(bar2, bar); 

    List<Foo> foos = Arrays.asList(foo2, foo); 

    //I would like to iterate foos and return a new foos sorted, and with bars sorted, so that this goes green 

    assertEquals(1, foos.get(0).sort); 
    assertEquals(1, foos.get(0).bars.get(0).sort); 
    assertEquals(2, foos.get(0).bars.get(1).sort); 
    assertEquals(2, foos.get(1).sort); 
    assertEquals(1, foos.get(1).bars.get(0).sort); 
    assertEquals(2, foos.get(1).bars.get(1).sort); 

} 

我已經試過這樣的流函數:

List<List<Bar>> foosSorted = foos.stream() 
     .sorted((o1, o2) -> Integer.compare(o1.sort, o2.sort)) 
     .map(f -> f.bars.stream().sorted((o1, o2) -> Integer.compare(o1.sort, o2.sort)).collect(Collectors.toList())) 
     .collect(Collectors.toList()); 

但這會返回Bar,而我想要一個Foo列表

+4

你想它修改現有的'Foo'對象(那會不會是非常實用...),或創建新的'Foo'與對象「Bar」對象的排序列表? –

+3

你應該首先想想你真正想做什麼。對就地包含在'Foo.bars'中的列表進行排序或創建'Foo'的新實例。在前一種情況下,只需在這些列表中調用'List.sort'。在後一種情況下,你必須在你的'map'操作中構建新的'Foo'實例。 – Holger

+0

我想要一個新的列表與排序的foos和排序的酒吧 –

回答

1
List<Foo> foosSort = foos.stream() 
        .sorted((o1, o2) -> (o1.sort - o2.sort)) 
        .map(f -> { 
          List<Bar> bars = f.bars.stream() 
          .sorted((o1, o2) -> (o1.sort- o2.sort)) 
          .collect(Collectors.toList()); 
          f.bars = bars; 
          return f; 
        }) 
        .collect(Collectors.toList()); 
+0

我不認爲這有效。 –

+0

它應該工作測試一次 – Nagarjuna

+0

我確認這也工作! –

4

以下將對和bars分別排序foo,但由於peek操作正在變異f,如果涉及到並行性,這將會出現意想不到的行爲。

List<Foo> foosSorted = foos.stream() 
      .sorted(Comparator.comparingInt(o -> o.sort)) 
      .peek(f -> { 
       f.bars = f.bars.stream().sorted(Comparator.comparingInt(o -> o.sort)).collect(Collectors.toList()); 
      }) 
      .collect(Collectors.toList()); 

我所說的其實是爲你增添的Foo一個構造採取sortbars和使用map代替peek。這樣,我們不會改變任何Foo對象,所以這可以並行運行而沒有麻煩。

List<Foo> foosSorted = foos.stream() 
      .sorted(Comparator.comparingInt(o -> o.sort)) 
      .map(f -> { 
       return new Foo(f.sort, f.bars.stream().sorted(Comparator.comparingInt(o -> o.sort)).collect(Collectors.toList())); 
      }) 
      .collect(Collectors.toList()); 

有:

class Foo { 
    public int sort; 
    public List<Bar> bars; 
    public Foo(int sort) { 
     this.sort = sort; 
    } 
    public Foo(int sort, List<Bar> bars) { 
     this.sort = sort; 
     this.bars = new ArrayList<>(bars); 
    } 
} 
+0

好的謝謝。我幾乎擁有它。我只需要在我的地圖操作中創建一個新的foo。謝謝! –

+1

''.peek(f - > {f.bars = expression;})'不需要花括號,它可以簡單地寫成'.peek(f - > f.bars = expression) ,也不在'.map(f - > {return expression;})'中,它可以簡單地寫成'.map(f - >表達式)'... – Holger