最近遇到個需求是這樣的:
寫一個類似於通訊錄的簡單功能,要求是首先按照部門顯示列表,然后點擊部門下拉顯示部門里面的人員信息,且人員信息按照職位排序。
先分析數據結構:
最外層是部門,部門里面是員工,且項目是統一返回數據格式。
{
"code": 0,
"data": [
{
"name": "部門名稱",
"userData": [
{
"deptName": "部門名稱",
"info": "部門名稱+職位",
"phone": "電話號碼",
"userName": "員工姓名"
}
]
},
{
"name": "部門名稱",
"userData": [
{
"deptName": "部門名稱",
"info": "部門名稱+職位",
"phone": "電話號碼",
"userName": "員工姓名"
}
]
}
],
"message": "success"
}
數據格式大概就是這樣。然后分析寫法。正常來說需要用sql將這些數據一次性分組並返回出來,本人沒有找到合適的方法。然后打算用最原始的方法,就是先查出所有的部門,再遍歷部門查詢出部門里面所有的人員,再將數據返回。下面貼上代碼。
List<PageData> deptAll = (List<PageData>) dao.findForList("AddressListMapper.querydeptAll", pageData);
//創建list保存所有部門和部門人員
List<PageData> deptPersonnelAll = new ArrayList<PageData>();
//遍歷獲取到的部門查詢相對應得人員信息
/* for (HashMap<String, Object> dept : deptAll) {
//獲取部門名稱
String deptName = String.valueOf(dept.get("name"));
//獲取部門code
String deptCode = String.valueOf(dept.get("code"));
//根據部門code查詢部門對應的人員
PageData pageDatap = new PageData();
pageDatap.put("deptid", deptCode);
ArrayList<PageData> personnelList = queryPersonnel(pageDatap);
//將數據存封裝為map並存進list
PageData deptSingle = new PageData();
deptSingle.put("name", deptName);
deptSingle.put("userData", personnelList);
deptPersonnelAll.add(deptSingle);
}*/
deptAll.stream().forEach(dept -> {
//獲取部門名稱
String deptName = String.valueOf(dept.get("name"));
//獲取部門code
String deptCode = String.valueOf(dept.get("code"));
//根據部門code查詢部門對應的人員
PageData pageDatap = new PageData();
pageDatap.put("deptid", deptCode);
ArrayList<PageData> personnelList = null;
try {
personnelList = queryPersonnel(pageDatap);
} catch (Exception e) {
e.printStackTrace();
}
//將數據存封裝為map並存進list
PageData deptSingle = new PageData();
deptSingle.put("name", deptName);
deptSingle.put("userData", personnelList);
deptPersonnelAll.add(deptSingle);
});
return deptPersonnelAll;
上面遍歷集合寫了兩種方式,一種是以前的for循環寫法,另一種是用表達式。
但是這種方式會出現一個性能問題,比如說有10000個部門,就需要查詢10000次數據庫。這樣會增大數據庫的壓力和查詢時間。所以這樣就需要優化。
優化:
優化的方式就是在數據一次查出所有的人員信息,並將人員信息和部門信息進行關聯,這樣就能知道每個人所對應的部門。然后用java代碼可以對數據進行分組。
貼代碼:
public List<Map<String, Object>> getAllPersonnel(PageData pageData) throws Exception {
//查詢類型對應的人員
List<AddressList> addressList = (List<AddressList>) dao.findForList("AddressListMapper.getAllPersonnel", pageData);
//lambda表達式對數據進行分組
Map<String, List<AddressList>> collect = addressList.stream().collect(Collectors.groupingBy(AddressList::getDeptName));
//處理分組后的數據
//創建一個list集合存儲所有數據
List<Map<String, Object>> maps = new ArrayList<>();
//遍歷分組后的數據,進行組裝
collect.forEach((k, v) -> {
HashMap<String, Object> map = new HashMap<>();
map.put("name", k);
map.put("userData", v);
maps.add(map);
});
return maps;
}
這邊分組是用的表達式分組的,定義一個對象,將數據庫查出來的數據封裝進去,然后按照屬性進行分組。這樣就可以避免多次請求數據庫。
處理排序:
這樣優化完后還有一個排序的問題。
解決辦法:
上面代碼中groupingBy有三個參數
第一個參數:分組按照什么分類
第二個參數:分組最后用什么容器保存返回值(默認是HashMap::new)
第三個參數:按照第一個參數分類后,對應的分類的結果如何收集。(Collectors.toList)
這邊主要問題是數據庫里面將數據排序好之后返回到代碼里面。代碼里面對數據進行分組之后,數據的順序發生了改變。
map里面的有序集合LinkedHashMap。這里可以使用這個集合作為分組后用來保存返回值的容器。這樣就解決了分組后的排序問題。