Java商品分类代码查询优化

编程入门 行业动态 更新时间:2024-10-20 05:29:27

Java<a href=https://www.elefans.com/category/jswz/34/1727078.html style=商品分类代码查询优化"/>

Java商品分类代码查询优化

需求:生活中常见页面一次性展示一级商品、二级商品、三级商品…甚至更多级别商品
大家通常会想到数据库一张表设计商品分类,有等级level字段,parent_id父id等关键设计字段

实体类也通常设计本实体关联子集的List

@TableName("item_cat")
@Data
@Accessors(chain = true)
public class ItemCat extends BasePojo{@TableId(type = IdType.AUTO)private Integer id;         //定义主键private Integer parentId;   //定义父级菜单private String name;        //分类名称private Boolean status;     //分类状态 0 停用 1 正常private Integer level;      //商品分类等级  1 2 3@TableField(exist = false)private List<ItemCat> children;
}

但java后台代码返回的lsit怎么包含各层级商品分类结构呢?

假设这里商品等级最多三级, 相信很多人首先想到的思路是:
先查询出一级商品,然后遍历一级商品,拿着一级商品的id去数据库查二级商品,然后又依次遍历二级商品,拿着二级商品的id去数据库查三级商品,常规代码如下

/*** 3层商品分类嵌套  1一级分类(children(2级商品分类))*                2一级分类(children(3级商品分类))* 一级查询条件   parent_id=0* 二级查询条件   parent_id=一级的ID* 三级查询条件   parent_id=二级的ID*/@Overridepublic List<ItemCat> findItemCatList(Integer level) {QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("parent_id", 0);List<ItemCat> list = itemCatMapper.selectList(queryWrapper);for (ItemCat oneItemCat : list) {queryWrapper.clear();queryWrapper.eq("parent_id", oneItemCat.getId());List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);oneItemCat.setChildren(twoList);for (ItemCat children : twoList) {queryWrapper.clear();queryWrapper.eq("parent_id", children.getId());children.setChildren(itemCatMapper.selectList(queryWrapper));}}return list;}

大家想过没有,以上代码执行效率非常低下,最大问题在于for循环的嵌套,嵌套太多层导致程序运行速度慢,占用内存高。假设一级商品有500种,对应的二级商品又有500种,这样至少查询数据库500*500=25000次,与数据库交互的频次太多,导致性能出现问题,所以以上代码非常不可取。

现要求,只查询一次数据库,即可获取3级商品分类信息。
大家想到思路没?没有想到的可以学习以下设计思路和代码,想到啦,看看以下思路是否是同一种思路,有好的建议,欢迎分享

设计

  1. 查询数据库中的所有的数据信息
  2. key: parentId value: 当前parentId下的所有的子级 封装成Map集合
  3. 将查询的结果封装到Map集合中
  4. 如需获取子级数据信息,通过getKey 即可获取数据

代码如下

/*** 1.准备Map集合,实现数据封装 Map<Key,Value> Map<parentId,List<ItemCat>>* 2.业务说明* map中的key~~~parentId 不存在 可以存储该key  设定key,同时封装一个list集合,将自己作为第一个元素封装到其中* 存在  根据key获取所有子集集合,将自己追加进去,形成第二个元素*/public Map<Integer, List<ItemCat>> itemCatMap() {Map<Integer, List<ItemCat>> map = new HashMap<>();//1.查询所有的数据库信息List<ItemCat> list = itemCatMapper.selectList(null);for (ItemCat itemCat : list) {int parentId = itemCat.getParentId();if (map.containsKey(parentId)) {//有key 获取list集合 将自己追加到集合中List<ItemCat> exeList = map.get(parentId);//引用对象,无需在putexeList.add(itemCat);} else {//没有key--将自己封装为第一个list元素List<ItemCat> firstList = new ArrayList<>();firstList.add(itemCat);map.put(parentId, firstList);}}return map;}@Overridepublic List<ItemCat> findItemCatList(Integer level) {Map<Integer, List<ItemCat>> map = itemCatMap();//1.如果level=1 说明获取一级商品分类信息 parent_id=0if (level == 1) {return map.get(0);}if (level == 2) {//2.获取二级商品信息,return getTwoList(map);}//3.获取三级商品信息//3.1 获取二级商品分类信息List<ItemCat> oneList = getTwoList(map);for (ItemCat oneItemCat : oneList) {List<ItemCat> twoList = oneItemCat.getChildren();//如果该元素没有2级列表,则跳过本次循环if (twoList == null || twoList.size() == 0) {continue;}for (ItemCat twoItemCat : twoList) {//查询三级商品分类 条件parentId=2级idtwoItemCat.setChildren(map.get(twoItemCat.getId()));}}return oneList;}/*** 获取二级商品分类信息(注:二级嵌套在一级集合中,所以永远返回的都是第一级)*/public List<ItemCat> getTwoList(Map<Integer, List<ItemCat>> map) {List<ItemCat> oneList = map.get(0);for (ItemCat oneItemCat : oneList) {//查询二级  parentId=1级idList<ItemCat> twoList = map.get(oneItemCat.getId());oneItemCat.setChildren(twoList);}//二级嵌套在一级集合中,所以永远返回的都是一级return oneList;}

如果支持无线级层呢,可看下来逻辑

public class MyTest {public static void main(String[] args) {List<TreeNode> singleNodes = new ArrayList<>();singleNodes.add(new TreeNode("a", "1", "节点1"));singleNodes.add(new TreeNode("b", "2", "节点2"));singleNodes.add(new TreeNode("4", "9", "节点1-1-1"));singleNodes.add(new TreeNode("c", "3", "节点3"));singleNodes.add(new TreeNode("2", "8", "节点2-2"));singleNodes.add(new TreeNode("1", "4", "节点1-1"));singleNodes.add(new TreeNode("9", "10", "节点1-1-1-1"));singleNodes.add(new TreeNode("2", "5", "节点2-1"));singleNodes.add(new TreeNode("1", "6", "节点1-3"));singleNodes.add(new TreeNode("1", "7", "节点1-2"));List<TreeNode> treeNodes = assmTree(singleNodes);System.out.println(JSON.toJSON(treeNodes));}/*** 组装树结构数据的方法*/public static List<TreeNode> assmTree(List<TreeNode> singleTreeNodes) {// 判断排序数据是否为空if (singleTreeNodes == null || singleTreeNodes.isEmpty()) {return null;}// 用有序Map把传参组装起来Map<String, TreeNode> nodeId2treeNodes = singleTreeNodes.stream().collect(Collectors.toMap(TreeNode::getNodeId, node -> node));// 用来保存组装好的数据, 作为返回值List<TreeNode> topNodeTrees = new ArrayList<>();// 遍历所有节点for (String nodeId : nodeId2treeNodes.keySet()) {TreeNode treeNode = nodeId2treeNodes.get(nodeId);String pid = treeNode.getPid();// 当前节点的父id为空 或 整个列表中没有以此父id作为自己的id的情况// 即当前节点是根节点if (pid == null || pid.length() == 0 || !nodeId2treeNodes.containsKey(pid)) {// treeNode.setPid(""); // 此处可以根据需要调整父id的值topNodeTrees.add(treeNode);} else { // 不是父节点, 作为子节点添加进去TreeNode parentTreeNode = nodeId2treeNodes.get(pid);if (parentTreeNode.getChildren() == null) {parentTreeNode.setChildren(new ArrayList<>());}parentTreeNode.getChildren().add(treeNode);}}return topNodeTrees;}}@Data
@NoArgsConstructor
class TreeNode {/*** 父节点ID*/private String pid;/*** 节点ID*/private String nodeId;/*** 节点名称*/private String nodeName;/*** 子节点*/private List<TreeNode> children;public TreeNode(String pid, String nodeId, String nodeName) {this.nodeId = nodeId;this.pid = pid;this.nodeName = nodeName;}}

更多推荐

Java商品分类代码查询优化

本文发布于:2024-02-11 11:50:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1680838.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:商品分类   代码   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!