三級(jí)分類之Stream的使用

參考

簡介

在跟著尚硅谷學(xué)習(xí)谷粒商城中遇到這個(gè)三級(jí)分類問題,使用了Stream Api,記錄一下

過程

主要內(nèi)容就是對(duì)商品類別表進(jìn)行三級(jí)分類,category表設(shè)計(jì)如下,主要關(guān)注,分類id,父分類id,排序這幾個(gè)字段

image

數(shù)據(jù)內(nèi)容,這里只貼了30條,總1000條,隨后在web上展示

image

了解了需求,CategoryEntity如下,關(guān)注新加入的非數(shù)據(jù)庫字段屬性List<CategoryEntity> children,用于存放該分類下的子分類

@Data
@TableName("pms_category")
public class CategoryEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 分類id
     */
    @TableId
    private Long catId;
    /**
     * 分類名稱
     */
    private String name;
    /**
     * 父分類id
     */
    private Long parentCid;
    /**
     * 層級(jí)
     */
    private Integer catLevel;
    /**
     * 是否顯示[0-不顯示,1顯示]
     */
    private Integer showStatus;
    /**
     * 排序
     */
    private Integer sort;
    /**
     * 圖標(biāo)地址
     */
    private String icon;
    /**
     * 計(jì)量單位
     */
    private String productUnit;
    /**
     * 商品數(shù)量
     */
    private Integer productCount;
    /**
     * 子分類
     */
    @TableField(exist = false)
    private List<CategoryEntity> children;

}

我們重點(diǎn)關(guān)注業(yè)務(wù)層,dao層使用的是Mybatis-Plus,不多介紹

就是在這里我們使用了Stream處理了從數(shù)據(jù)庫查到的所有分類信息

處理過程:

  • 從數(shù)據(jù)庫查到所有分類信息List<CategoryEntity>
  • 先查到所有的一級(jí)分類(parentCid為0的,從上面的數(shù)據(jù)內(nèi)容也可看出來)
  • 接著從這些父分類,找到屬于他的子分類(通過getChildren函數(shù))
  • sorted根據(jù)sort字段升序排列
  • collect形成集合
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    ...

    @Override
    public List<CategoryEntity> listWithTree() {
        // 1、查出所有分類
        List<CategoryEntity> entities = baseMapper.selectList(null);
        // 2、組裝樹形結(jié)構(gòu)

        // 2.1、一級(jí)分類
        List<CategoryEntity> level1Menu = entities.stream().filter((categoryEntity) ->
                categoryEntity.getParentCid() == 0
        ).peek((menu) ->
                menu.setChildren(getChildren(menu, entities))
        ).sorted(
                Comparator.comparingInt(CategoryEntity::getSort)
        ).collect(Collectors.toList());
        return level1Menu;
    }

    /**
     * 遞歸查找所有菜單的子菜單
     * @param root
     * @param all
     * @return
     */
    private List<CategoryEntity> getChildren(CategoryEntity root, List<CategoryEntity> all) {
        List<CategoryEntity> children = all.stream().filter((categoryEntity ->
                categoryEntity.getParentCid().equals(root.getCatId()))
        ).peek((categoryEntity ->
                categoryEntity.setChildren(getChildren(categoryEntity, all)))
        ).sorted(
                Comparator.comparingInt(CategoryEntity::getSort)
        ).collect(Collectors.toList());
        return children;
    }
    
    ...
        
}

最后web顯示如下,我使用的JSONView插件,也可以用F12查看相關(guān)信息

image-20210808171639929

結(jié)果就是我們期望的結(jié)果,觀察發(fā)現(xiàn)排序也正確,“手機(jī)”排在首位

思考

如果這個(gè)業(yè)務(wù)不使用Stream該怎么做,會(huì)有多復(fù)雜,從這里就可體會(huì)到Stream的強(qiáng)大

使用Stream,需要哪些知識(shí)?

首先作為JDK1.8的重點(diǎn)升級(jí),JDK1.8的lambda表達(dá)式、函數(shù)式接口、鏈?zhǔn)骄幊潭际侵攸c(diǎn)

四大函數(shù)式接口

這些都可以直接搜源碼看接口怎樣設(shè)計(jì)的就明白怎么用了,下面我用白話概括一下

Function 函數(shù)式接口

傳入一個(gè)參數(shù),由這個(gè)參數(shù)返回值

Predicate 斷言型接口

傳入一個(gè)參數(shù),由這個(gè)參數(shù)進(jìn)行判斷,返回布爾值

Consumer 消費(fèi)型接口

傳入一個(gè)參數(shù),由這個(gè)參數(shù)進(jìn)行處理,無返回

Supplier 供給型接口

無參數(shù),返回一個(gè)值

回想

在使用Stream其實(shí)就是傳入一些函數(shù)式接口,再結(jié)合使用lambda表達(dá)式就變得非常簡便

想想但是學(xué)的使用體會(huì)還沒有這么大,直到遇見了真的業(yè)務(wù),感受就馬上不同了

總結(jié)

此后,我終于能體會(huì)到一些算法題的業(yè)務(wù)場(chǎng)景了,還有JavaSE基礎(chǔ)真的很重要,更多的得慢慢感受了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容