java8lambda表達式對集合分組並且排序(記一次性能優化案例)


最近遇到個需求是這樣的:

寫一個類似於通訊錄的簡單功能,要求是首先按照部門顯示列表,然后點擊部門下拉顯示部門里面的人員信息,且人員信息按照職位排序。

先分析數據結構:

最外層是部門,部門里面是員工,且項目是統一返回數據格式。

{
    "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。這里可以使用這個集合作為分組后用來保存返回值的容器。這樣就解決了分組后的排序問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM