大家好,又見面了。 在我前面的文章《吃透JAVA的Stream流操作,多年實踐總結》中呢,對Stream的整體情況進行了細緻全面的講解,也大概介紹了下結果收集器Collectors的常見用法 —— 但遠不是全部。 本篇文章就來專門剖析collect操作,一起解鎖更多高級玩法,讓Stream操作真正的 ...
大家好,又見面了。
在我前面的文章《吃透JAVA的Stream流操作,多年實踐總結》中呢,對Stream的整體情況進行了細緻全面的講解,也大概介紹了下結果收集器Collectors
的常見用法 —— 但遠不是全部。
本篇文章就來專門剖析collect操作,一起解鎖更多高級玩法,讓Stream操作真正的成為我們編碼中的神兵利器。
初識Collector
先看一個簡單的場景:
現有集團內所有人員列表,需要從中篩選出上海子公司的全部人員
假定人員信息數據如下:
姓名 | 子公司 | 部門 | 年齡 | 工資 |
---|---|---|---|---|
大壯 | 上海公司 | 研發一部 | 28 | 3000 |
二牛 | 上海公司 | 研發一部 | 24 | 2000 |
鐵柱 | 上海公司 | 研發二部 | 34 | 5000 |
翠花 | 南京公司 | 測試一部 | 27 | 3000 |
玲玲 | 南京公司 | 測試二部 | 31 | 4000 |
如果你曾經用過Stream流,或者你看過我前面關於Stream用法介紹的文章,那麼藉助Stream可以很輕鬆的實現上述訴求:
public void filterEmployeesByCompany() {
List<Employee> employees = getAllEmployees().stream()
.filter(employee -> "上海公司".equals(employee.getSubCompany()))
.collect(Collectors.toList());
System.out.println(employees);
}
上述代碼中,先創建流,然後通過一系列中間流操作(filter
方法)進行業務層面的處理,然後經由終止操作(collect
方法)將處理後的結果輸出為List對象。
但我們實際面對的需求場景中,往往會有一些更複雜的訴求,比如說:
現有集團內所有人員列表,需要從中篩選出上海子公司的全部人員,並按照部門進行分組
其實也就是加了個新的分組訴求,那就是先按照前面的代碼實現邏輯基礎上,再對結果進行分組處理就好咯:
public void filterEmployeesThenGroup() {
// 先 篩選
List<Employee> employees = getAllEmployees().stream()
.filter(employee -> "上海公司".equals(employee.getSubCompany()))
.collect(Collectors.toList());
// 再 分組
Map<String, List<Employee>> resultMap = new HashMap<>();
for (Employee employee : employees) {
List<Employee> groupList = resultMap
.computeIfAbsent(employee.getDepartment(), k -> new ArrayList<>());
groupList.add(employee);
}
System.out.println(resultMap);
}
似乎也沒啥毛病,相信很多同學實際編碼中也是這麼處理的。但其實我們也可以使用Stream操作直接完成:
public void filterEmployeesThenGroupByStream() {
Map<String, List<Employee>> resultMap = getAllEmployees().stream()
.filter(employee -> "上海公司".equals(employee.getSubCompany()))
.collect(Collectors.groupingBy(Employee::getDepartment));
System.out.println(resultMap);
}
兩種寫法都可以得到相同的結果:
{
研發二部=[Employee(subCompany=上海公司, department=研發二部, name=鐵柱, age=34, salary=5000)],
研發一部=[Employee(subCompany=上海公司, department=研發一部, name=大壯, age=28, salary=3000),
Employee(subCompany=上海公司, department=研發一部, name=二牛, age=24, salary=2000)]
}
上述2種寫法相比而言,第二種是不是代碼上要簡潔很多?而且是不是有種自註釋的味道了?
通過collect方法的合理恰當利用,可以讓Stream適應更多實際的使用場景,大大的提升我們的開發編碼效率。下麵就一起來全面認識下collect、解鎖更多高級操作吧。
collect\Collector\Collectors區別與關聯
剛接觸Stream收集器的時候,很多同學都會被collect
,Collector
,Collectors
這幾個概念搞的暈頭轉向,甚至還有很多人即使已經使用Stream好多年,也只是知道collect裡面需要傳入類似Collectors.toList()
這種簡單的用法,對其背後的細節也不甚瞭解。
這裡以一個collect收集器最簡單的使用場景來剖析說明下其中的關係: