2015-12-08 81 views
2

我是java Stream API的新手,並且有解決使用它的用例。在java中分組8 8 Stream API

Map<Object, ? extends Object> map = list.stream().collect(Collectors.groupingBy(p->p.getX() 
                  ,Collectors.groupingBy(p->p.getY() 
                  ,Collectors.groupingBy(p->p.getZ())))); 

考慮到x,y和z是給定類的屬性。如果我們具有預定義的分組順序(哪個屬性需要考慮第一個,第二個等...),這可以正常工作。

(給定的一段代碼屬性x被認爲是1st,y 2nd和z 3rd)。

現在,就我而言,分組的順序不是預定義的,可能會在運行時更改。所以,在編譯時,我不知道在collect方法中傳遞什麼。 我正在尋找一種解決方案,通過該解決方案,我可以讀取配置字符串並在運行時更改分組。

+0

你是什麼意思「讀取配置串並改變在分組運行。」? – Tunaki

+0

好的,讓我們假設它是用戶定義的 - 所以如果用戶定義了groupingOrder = x,y,z它應該如上所述分組,如果另一個用戶將其定義爲y,x,z,它應該相應地改變..(* groupingOrder只是我的名字作爲參考) – Sachin

回答

1

您可以創建使用給定的分類功能,它建立自己Collector一個輔助方法:

@SuppressWarnings("unchecked") 
@SafeVarargs 
public static <T> Collector<T, ?, Map<?, ?>> multiGrouping(
               Function<? super T, ?>... classifiers) { 
    Collector<T, ?, Map<?, ?>> result = null; 
    for(int i=classifiers.length-1; i>=0; i--) { 
     Collector<?, ?, ?> next; 
     if(result == null) { 
      next = Collectors.groupingBy(classifiers[i]); 
     } else { 
      next = Collectors.groupingBy(classifiers[i], result); 
     } 
     result = (Collector<T, ?, Map<?, ?>>)next; 
    } 
    return result; 
} 

用例:

Map<?, ?> map = Stream.of("abc", "def", "cd", "cfff") 
         .collect(multiGrouping(String::length, s -> s.charAt(0))); 
+0

謝謝,明白了..我正在尋找相同的.. – Sachin

1

假設pP類的,你可以定義的順序是這樣的:

Function<P, Object> g1 = P::getX; 
Function<P, Object> g2 = P::getX; 
Function<P, Object> g3 = P::getX; 

然後:

list.stream().collect(Collectors.groupingBy(g1, 
         Collectors.groupingBy(g2, 
          Collectors.groupingBy(g3)))); 

的G1,G2,G3也可以使用反射來訪問定義基於字段/方法名稱的運行時方法/字段。

+0

感謝您的快速回復,在這種情況下,我是否需要定義所有屬性的順序?我想在運行時基於配置字符串構造「Collectors.groupingBy(...」作爲字符串(如**「list.stream()。collect(Collectors.groupingBy(g1,Collectors.groupingBy(g2, Collectors.groupingBy(g3))));「**然後使用groovy執行它,但它似乎像當前的常規版本不支持lambda .. – Sachin