2017-01-03 64 views
3

我想用兩列使用Collectors.groupingBy分組。Collectors.grouping由兩列不起作用

我寫了下面:

public class TestGroupKey 
{ 
    public static void main(String... args) { 
     List<Item> list = Arrays.asList(
      new Item(1, 1, 1), 
      new Item(1, 1, 2), 
      new Item(1, 1, 3), 
      new Item(1, 2, 1), 
      new Item(1, 2, 2), 
      new Item(2, 1, 1), 
      new Item(2, 2, 1), 
      new Item(2, 3, 1), 
      new Item(2, 4, 1), 
      new Item(2, 4, 2), 
      new Item(2, 4, 3), 
      new Item(2, 4, 4), 
      new Item(3, 1, 1), 
      new Item(3, 1, 2), 
      new Item(3, 1, 3), 
      new Item(3, 1, 4), 
      new Item(3, 2, 1), 
      new Item(3, 2, 2) 
     ); 

     Map<CustomKey, List<Item>> tupleGrouping = 
      list.stream().collect(Collectors.groupingBy(item -> item.customKey)); 
     tupleGrouping.entrySet().stream() 
       .forEach(entry -> { 
        System.out.println(entry.getKey()); 
       }); 
    } 

    public static class Item { 
     public int topLevelId; 
     public int secondLevelId; 
     public int itemId; 
     public CustomKey customKey; 

     public Item(int topLevelId, int secondLevelId, int itemId) { 
      this.topLevelId = topLevelId; 
      this.secondLevelId = secondLevelId; 
      this.itemId = itemId; 
      this.customKey = new CustomKey(topLevelId, secondLevelId); 
     } 

     @Override 
     public String toString() { 
      return String.format("%d%d%d", this.topLevelId, this.secondLevelId, this.itemId); 
     } 
    } 

    public static class CustomKey { 
     public int topLevelId; 
     public int secondLevelId; 

     public CustomKey(int topLevelId, int secondLevelId) { 
      this.topLevelId = topLevelId; 
      this.secondLevelId = secondLevelId; 
     } 

     @Override 
     public String toString() { 
      return String.format("%d%d", this.topLevelId, this.secondLevelId); 
     } 
    } 
} 

預期的結果是

11 
12 
21 
22 
23 
24 
31 
32 

但實際的結果是

24 
31 
23 
22 
12 
21 
24 
31 
31 
24 
12 
32 
32 
11 
11 
11 
31 

我覺得groupingBy不能正常工作。

我使用​​類時出現了什麼問題?

此外,嵌套地圖鍵工作:

Map<Integer, Map<Integer, List<Item>>> entryGrouping = 
    list.stream() 
     .collect(Collectors.groupingBy(atta1 -> atta1.topLevelId, 
             Collectors.groupingBy(atta2 -> atta2.secondLevelId))); 
+1

作爲邊注,'tupleGrouping.entrySet()流().forEach(條目 - > {的System.out.println(entry.getKey());});'是相當令人費解,相比tupleGrouping.keySet()。forEach(System.out :: println);'或'tupleGrouping.forEach((k,v) - > System.out.println(k));'... – Holger

回答

5

你​​類沒有重載的Objectequals方法,所以groupingBy考慮兩個​​s到只有當它們是相同的對象相等(這在你的例子中從來都不是真的,因爲你爲每個Item創建一個新的​​實例)。 。

public static class CustomKey { 
    ... 
    @Override 
    public int hashCode() 
    { 
     // if you override equals, you should also override hashCode 
    } 

    @Override 
    public boolean equals (Object other) 
    { 
     if (other == this) 
      return true; 
     if (!(other instanceof CustomKey)) 
      return false; 
     CustomKey okey = (CustomKey) other; 
     return this.topLevelId == okey.topLevelId && this.secondLevelId == okey.secondLevelId; 
    } 
    ... 
} 
+0

謝謝!我勝過平等。但是,當override等於時,我忘記了重寫hashCode。 – Wishgone