1.现有代码存在的问题
@Override
public List<ItemCat> findItemCatList(Integer level) {
//性能问题:!!!!!
long startTime = System.currentTimeMillis();
//1.查询一级商品分类信息
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0);
List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//2.查询二级商品分类信息 遍历一级集合
for(ItemCat oneItemCat : oneList){
queryWrapper.clear(); //清空条件
queryWrapper.eq("parent_id", oneItemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
//3.查询三级商品分类信息 遍历
for(ItemCat twoItemCat : twoList){
queryWrapper.clear();
queryWrapper.eq("parent_id", twoItemCat.getId());
List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
//将三级封装给二级
twoItemCat.setChildren(threeList);
}
//3.将二级记录封装给一级
oneItemCat.setChildren(twoList);
}
//记录程序的结束时间
long endTime = System.currentTimeMillis();
System.out.println("查询耗时:"+(endTime - startTime)+"毫秒");
return oneList;
}
问题说明: 如果经过2次for循环, 链接数据库的次数将会很多, 直接影响查询的效率.
优化: 尽可能的降低查询的次数,同时满足用户需求.
2.优化策略
数据结构: Map<K,V> map
Key=“父级ID” Value=List<当前父级的子级>
用法: 如果想要获取任意父级的子级 map.get(父级的ID)
用法说明: Value 只有父级的子级信息,没有嵌套结构
Map<父级ID,List<ItemCat{id=xx,name=xx,children=null}>>
2.1封装Map实现完整代码
/**
* 1.封装Map集合 Map<Key=父级ID,value=List<ItemCat对象>>
* 2.说明: 将所有的数据库的父子关系,进行封装.(没有嵌套!!!!)
* 3.优势: 只查询一次数据库,就可以完成父子关系的封装.
策略:
* 1. key不存在, 准备一个新List集合,将自己当作第一个元素追加
* 2. key存在, 获取原有list集合,将自己追加.
*
*/
public Map<Integer,List<ItemCat>> initMap(){
//Map中包含了所有的父子级关系.
Map<Integer,List<ItemCat>> map = new HashMap<>();
//1.查询item_cat表中的所有的记录(1/2/3级菜单)
List<ItemCat> itemCatList = itemCatMapper.selectList(null);
//2.实现数据的封装
for(ItemCat itemCat : itemCatList){
int key = itemCat.getParentId();
if(map.containsKey(key)){ //存在
List<ItemCat> list = map.get(key);
//将自己追加到其中
list.add(itemCat);
}else{ //不存在: 准备List集合,将自己作为第一个元素封装
List<ItemCat> list = new ArrayList<>();
list.add(itemCat);
map.put(key,list);
}
}
//将封装的数据进行返回.
return map;
}
/**
* level 1 只查询一级商品分类
* 2 查询一级/二级 嵌套封装
* 3 查询一级/二级/三级 嵌套封装
* @param level
* @return
*/
@Override
public List<ItemCat> findItemCatList(Integer level) {
long startTime = System.currentTimeMillis();
//Map集合里边封装的是所有的父子级关系.
Map<Integer,List<ItemCat>> map = initMap();
if(level == 1){ //只获取1级菜单. parent_id = 0
return map.get(0);
}
//用户查询1/2级商品分类信息
if(level == 2){
return getLevel2List(map);
}
//如果程序执行到这里,则说明用户查询的是1-2-3级菜单
List<ItemCat> list = getLevel3List(map);
long endTime = System.currentTimeMillis();
System.out.println("耗时:"+(endTime-startTime)+"毫秒");
return list;
}
public List<ItemCat> getLevel3List(Map<Integer, List<ItemCat>> map) {
//1.先查询1-2级
List<ItemCat> oneList = getLevel2List(map);
//2.遍历集合
for(ItemCat oneItemCat : oneList){
//获取二级集合信息
List<ItemCat> twoList = oneItemCat.getChildren();
if(twoList == null || twoList.size() ==0){
//当前一级菜单没有二级元素.结束本次循环,开始下一次!!!
continue;
}
//该元素有二级,应该查询三级.
for(ItemCat twoItemCat : twoList){
List<ItemCat> threeList = map.get(twoItemCat.getId());
twoItemCat.setChildren(threeList);
}
}
return oneList;
}
//查询一级和二级信息
public List<ItemCat> getLevel2List(Map<Integer, List<ItemCat>> map) {
//思路: 先查询一级,之后循环遍历,再次封装2级
//1.获取一级
List<ItemCat> oneList = map.get(0);
for(ItemCat oneItemCat : oneList){
//2.如何根据一级查询二级? 通过Map集合获取
List<ItemCat> twoList = map.get(oneItemCat.getId());
//3.实现了一级二级的封装
oneItemCat.setChildren(twoList);
}
return oneList;
}