1.現(xiàn)有代碼存在的問題
@Override
public List<ItemCat> findItemCatList(Integer level) {
//性能問題:!!!!!
long startTime = System.currentTimeMillis();
//1.查詢一級(jí)商品分類信息
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0);
List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//2.查詢二級(jí)商品分類信息 遍歷一級(jí)集合
for(ItemCat oneItemCat : oneList){
queryWrapper.clear(); //清空條件
queryWrapper.eq("parent_id", oneItemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
//3.查詢?nèi)?jí)商品分類信息 遍歷
for(ItemCat twoItemCat : twoList){
queryWrapper.clear();
queryWrapper.eq("parent_id", twoItemCat.getId());
List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
//將三級(jí)封裝給二級(jí)
twoItemCat.setChildren(threeList);
}
//3.將二級(jí)記錄封裝給一級(jí)
oneItemCat.setChildren(twoList);
}
//記錄程序的結(jié)束時(shí)間
long endTime = System.currentTimeMillis();
System.out.println("查詢耗時(shí):"+(endTime - startTime)+"毫秒");
return oneList;
}
問題說明: 如果經(jīng)過2次for循環(huán), 鏈接數(shù)據(jù)庫的次數(shù)將會(huì)很多, 直接影響查詢的效率.
優(yōu)化: 盡可能的降低查詢的次數(shù),同時(shí)滿足用戶需求.
2.優(yōu)化策略
數(shù)據(jù)結(jié)構(gòu): Map<K,V> map
Key=“父級(jí)ID” Value=List<當(dāng)前父級(jí)的子級(jí)>
用法: 如果想要獲取任意父級(jí)的子級(jí) map.get(父級(jí)的ID)
用法說明: Value 只有父級(jí)的子級(jí)信息,沒有嵌套結(jié)構(gòu)
Map<父級(jí)ID,List<ItemCat{id=xx,name=xx,children=null}>>

原理圖
2.1封裝Map實(shí)現(xiàn)完整代碼
/**
* 1.封裝Map集合 Map<Key=父級(jí)ID,value=List<ItemCat對(duì)象>>
* 2.說明: 將所有的數(shù)據(jù)庫的父子關(guān)系,進(jìn)行封裝.(沒有嵌套!!!!)
* 3.優(yōu)勢(shì): 只查詢一次數(shù)據(jù)庫,就可以完成父子關(guān)系的封裝.
策略:
* 1. key不存在, 準(zhǔn)備一個(gè)新List集合,將自己當(dāng)作第一個(gè)元素追加
* 2. key存在, 獲取原有l(wèi)ist集合,將自己追加.
*
*/
public Map<Integer,List<ItemCat>> initMap(){
//Map中包含了所有的父子級(jí)關(guān)系.
Map<Integer,List<ItemCat>> map = new HashMap<>();
//1.查詢item_cat表中的所有的記錄(1/2/3級(jí)菜單)
List<ItemCat> itemCatList = itemCatMapper.selectList(null);
//2.實(shí)現(xiàn)數(shù)據(jù)的封裝
for(ItemCat itemCat : itemCatList){
int key = itemCat.getParentId();
if(map.containsKey(key)){ //存在
List<ItemCat> list = map.get(key);
//將自己追加到其中
list.add(itemCat);
}else{ //不存在: 準(zhǔn)備List集合,將自己作為第一個(gè)元素封裝
List<ItemCat> list = new ArrayList<>();
list.add(itemCat);
map.put(key,list);
}
}
//將封裝的數(shù)據(jù)進(jìn)行返回.
return map;
}
/**
* level 1 只查詢一級(jí)商品分類
* 2 查詢一級(jí)/二級(jí) 嵌套封裝
* 3 查詢一級(jí)/二級(jí)/三級(jí) 嵌套封裝
* @param level
* @return
*/
@Override
public List<ItemCat> findItemCatList(Integer level) {
long startTime = System.currentTimeMillis();
//Map集合里邊封裝的是所有的父子級(jí)關(guān)系.
Map<Integer,List<ItemCat>> map = initMap();
if(level == 1){ //只獲取1級(jí)菜單. parent_id = 0
return map.get(0);
}
//用戶查詢1/2級(jí)商品分類信息
if(level == 2){
return getLevel2List(map);
}
//如果程序執(zhí)行到這里,則說明用戶查詢的是1-2-3級(jí)菜單
List<ItemCat> list = getLevel3List(map);
long endTime = System.currentTimeMillis();
System.out.println("耗時(shí):"+(endTime-startTime)+"毫秒");
return list;
}
public List<ItemCat> getLevel3List(Map<Integer, List<ItemCat>> map) {
//1.先查詢1-2級(jí)
List<ItemCat> oneList = getLevel2List(map);
//2.遍歷集合
for(ItemCat oneItemCat : oneList){
//獲取二級(jí)集合信息
List<ItemCat> twoList = oneItemCat.getChildren();
if(twoList == null || twoList.size() ==0){
//當(dāng)前一級(jí)菜單沒有二級(jí)元素.結(jié)束本次循環(huán),開始下一次!!!
continue;
}
//該元素有二級(jí),應(yīng)該查詢?nèi)?jí).
for(ItemCat twoItemCat : twoList){
List<ItemCat> threeList = map.get(twoItemCat.getId());
twoItemCat.setChildren(threeList);
}
}
return oneList;
}
//查詢一級(jí)和二級(jí)信息
public List<ItemCat> getLevel2List(Map<Integer, List<ItemCat>> map) {
//思路: 先查詢一級(jí),之后循環(huán)遍歷,再次封裝2級(jí)
//1.獲取一級(jí)
List<ItemCat> oneList = map.get(0);
for(ItemCat oneItemCat : oneList){
//2.如何根據(jù)一級(jí)查詢二級(jí)? 通過Map集合獲取
List<ItemCat> twoList = map.get(oneItemCat.getId());
//3.實(shí)現(xiàn)了一級(jí)二級(jí)的封裝
oneItemCat.setChildren(twoList);
}
return oneList;
}
3.優(yōu)化后結(jié)果對(duì)比
優(yōu)化前:
