繼前面提到的基本操作之後,在這邊要討論的部分是如何利用Stream reference搭配Lambda表
式示的語法,再加上Collectors類別下的groupingBy method將List下的類別物件進行分組的動
作,如此一來可以達到類似SQL語法下做group by針對某些欄位分組的行為。
首先,一樣套用前面基本操作文章有提到的Transcript class來建立一List,並且多定義了一
成員變數sex,來針對每一筆Transcript能區別出為Male or Female。
基本建置語法改寫如下:
多定義了一個性別屬性,來達到做分組的示範。
#單一條件群組的使用
1. Collectors.groupingBy使用
再來,基本的群組的使用語法如下:
說明如下:
一樣利用stream reference使用collect,此時在參數的地方assign的是Collectors.groupingBy
,其將針對stream reference所擁有的Transcript物件進行分組,而分組的條件為
Transcript::getSex。在Java多載之下,因應collect所帶入的參數在此時為回傳Map型態物件
,並且在這邊依據groupingBy的型態對應至Map的key也為String型態,而value不諱言應該
就是List<Transcript>了,因為sex可能對應至多個Transcript物件。
PS. Transcript::getSex為Lambda語法的簡寫型式,相當於Transcript t -> t.getSex()
2. Collectors.joining使用
在得到一回傳分組物件Map<String, List<Transcript>>後,接下來就是進行print的動作了。
首先,在這邊stream reference使用map的目的為,將Transcript object轉換成String,且只有
針對Name的部分。
PS. 在此只是要示範出,Male or Female的部分各別為哪一些人!
再來,當您取出Name之後可以怎麼陳列呢? 在一個群組有多個Name的當下,利用join來達
到多個字串的串接,並且這個method有個方便的設計,不只是針對要串接的符號為啥,
還可以針對頭跟尾設定串接哪個字串來達到使用join的完整性!
PS. 相信有使用過JavaScript的人大概都知道join可以達到什麼功用囉!
#多個條件群組的使用
參考資料 Java 8 Lamdas技術手冊
式示的語法,再加上Collectors類別下的groupingBy method將List下的類別物件進行分組的動
作,如此一來可以達到類似SQL語法下做group by針對某些欄位分組的行為。
首先,一樣套用前面基本操作文章有提到的Transcript class來建立一List,並且多定義了一
成員變數sex,來針對每一筆Transcript能區別出為Male or Female。
class Transcript{
....
private String sex;
...
public Transcript(int id, String name, String sex, int chinese, int math, int english) {
super();
this.id = id;
this.sex = sex;
...
}
....
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
基本建置語法改寫如下:
List<Transcript> studentList = new ArrayList<Transcript>();
Transcript t1 = new Transcript(2,"Ben", "Male", 87, 91, 80);
Transcript t2 = new Transcript(1,"Sjkok", "Female", 94, 99, 65);
Transcript t3 = new Transcript(3,"Aaron", "Male", 44, 55, 100);
Transcript t4 = new Transcript(4,"Zhibin", "Male", 77, 88, 66);
studentList.add(t1);
studentList.add(t2);
studentList.add(t3);
studentList.add(t4);
多定義了一個性別屬性,來達到做分組的示範。
#單一條件群組的使用
1. Collectors.groupingBy使用
再來,基本的群組的使用語法如下:
Map<String, List<Transcript>> transBySex = null;
transBySex = studentList.stream()
.collect(Collectors.groupingBy(Transcript::getSex));
說明如下:
一樣利用stream reference使用collect,此時在參數的地方assign的是Collectors.groupingBy
,其將針對stream reference所擁有的Transcript物件進行分組,而分組的條件為
Transcript::getSex。在Java多載之下,因應collect所帶入的參數在此時為回傳Map型態物件
,並且在這邊依據groupingBy的型態對應至Map的key也為String型態,而value不諱言應該
就是List<Transcript>了,因為sex可能對應至多個Transcript物件。
PS. Transcript::getSex為Lambda語法的簡寫型式,相當於Transcript t -> t.getSex()
2. Collectors.joining使用
transBySex.forEach((sex, trans) -> {
System.out.println(sex+"=>"+
trans.stream()
.map(t -> t.getName())
.collect(Collectors.joining(", ", "[", "]")));
});
在得到一回傳分組物件Map<String, List<Transcript>>後,接下來就是進行print的動作了。
首先,在這邊stream reference使用map的目的為,將Transcript object轉換成String,且只有
針對Name的部分。
PS. 在此只是要示範出,Male or Female的部分各別為哪一些人!
再來,當您取出Name之後可以怎麼陳列呢? 在一個群組有多個Name的當下,利用join來達
到多個字串的串接,並且這個method有個方便的設計,不只是針對要串接的符號為啥,
還可以針對頭跟尾設定串接哪個字串來達到使用join的完整性!
PS. 相信有使用過JavaScript的人大概都知道join可以達到什麼功用囉!
#多個條件群組的使用
在這邊要示範的是,在分組的時候,針對該分組能夠達到得進一步設定,在此為以sex分組
後,如何針對該分組下的單一科目分數取得大家的平均值! 主要是需設定一downstream。
Java 8 API說明如下:
語法使用如下:
Map<String, Double> avgMathBySex = null;
avgMathBySex = studentList.stream()
.collect(Collectors.groupingBy(Transcript::getSex,
Collectors.averagingInt(Transcript::getMath)));
avgMathBySex.forEach((sex , avgmath) -> System.out.println(sex+"=>"+avgmath));
在此另一參數,會回傳該分組下的Transcript物件下某一屬性的平均值,至於是哪個屬性,
在此指定為Math,因此最後collect會依據collect內的參數回傳型態來推斷出Map對應的
key為String及value為Double。
PS. Collectors.averagingInt計算後回傳的數值為Double並非Integer!
最後,所有範例列印的結果:
留言
張貼留言