Java高效编程

函数式编程

需求

有一些商品信息,现在需要将这些商品添加到购物车中获取购物车中的商品信息,然后完成以下需求.

  1. 找出购物车中所有属于电子数码 的商品
  2. 根据商品类型查找商品
  3. 通过商品类型或总价过滤商品
  4. 根据不同的商品判断标准查找商品

商品实体类

java 复制代码
package lambda.cart;

/**
 * 下单商品信息对象
 */
public class Sku {
    // 商品编号
    private Integer skuId;
    // 商品名称
    private String skuName;
    // 商品单价
    private Double skuPrice;
    // 商品个数
    private Integer totalNum;
    // 商品总价
    private Double totalPrice;
    // 商品分类
    private Enum skuCategory;


    /**
     * 有参构造
     * @param skuId
     * @param skuName
     * @param skuPrice
     * @param totalNum
     * @param totalPrice
     * @param skuCategory
     */
    public Sku(Integer skuId, String skuName, Double skuPrice, Integer totalNum, Double totalPrice, Enum skuCategory) {
        this.skuId = skuId;
        this.skuName = skuName;
        this.skuPrice = skuPrice;
        this.totalNum = totalNum;
        this.totalPrice = totalPrice;
        this.skuCategory = skuCategory;
    }

    public Integer getSkuId() {
        return skuId;
    }

    public String getSkuName() {
        return skuName;
    }

    public Double getSkuPrice() {
        return skuPrice;
    }

    public Integer getTotalNum() {
        return totalNum;
    }

    public Double getTotalPrice() {
        return totalPrice;
    }

    public Enum getSkuCategory() {
        return skuCategory;
    }
}

商品分类枚举

java 复制代码
package lambda.cart;

/**
 * 商品分类枚举
 */
public enum SkuCategoryEnum {
    CLOTHING(10, "服装"),
    DIGITAL(20, "数码产品"),
    SPORTS(30, "运动类"),
    BOOKS(40, "书籍类");

    // 商品类型的编号
    private Integer code;
    // 商品类型的名称
    private String name;

    /**
     * 构造方法
     *
     * @param code
     * @param name
     */
    SkuCategoryEnum(Integer code, String name) {
        this.code = code;
        this.name = name;
    }


}

添加所有商品信息到购物车中

java 复制代码
private static List<Sku> cartSkuList = new ArrayList<Sku>() {
        {
            add(new Sku(654032, "无人机", 22.2, 2, 44.4, SkuCategoryEnum.DIGITAL));
            add(new Sku(654033, "VR眼镜", 11.1, 2, 22.2, SkuCategoryEnum.DIGITAL));
            add(new Sku(654034, "充气娃娃", 1000.0, 2, 2000.0, SkuCategoryEnum.SPORTS));
            add(new Sku(654035, "Java核心技术", 50.0, 2, 100.0, SkuCategoryEnum.BOOKS));
            add(new Sku(654036, "Python编程", 49.0, 2, 96.0, SkuCategoryEnum.BOOKS));
            add(new Sku(654037, "女装", 66.0, 1, 66.0, SkuCategoryEnum.CLOTHING));
        }
    };

获取购物车中的所有商品

java 复制代码
public static List<Sku> getCartSkuList() {
        return cartSkuList;
    }

需求分析和完成

找出购物车中所有属于电子数码的商品

  • 实现方式:使用循环遍历购物车中的所有商品信息,然后使用枚举进行比对
java 复制代码
public static List<Sku> filterElectronicsSku(List<Sku> cartSkuList) {
        List<Sku> result = new ArrayList<>();
        for (Sku sku : cartSkuList
        ) {
            if (SkuCategoryEnum.DIGITAL.equals(sku.getSkuCategory())) {
                result.add(sku);
            }
        }
        return result;
    }

根据商品类型查找商品

  • 实现方式:将商品类别枚举作为参数传递给方法,使用商品分类枚举进行比对
java 复制代码
/**
     * 根据商品类型查找商品
     * Version:2.0(单一维度条件参数化)
     *
     * @param cartSkuList
     * @param skuCategoryEnum
     * @return
     */
    public static List<Sku> filterSkuByCategory(List<Sku> cartSkuList, SkuCategoryEnum skuCategoryEnum) {
        List<Sku> result = new ArrayList<>();
        for (Sku sku : cartSkuList
        ) {
            if (skuCategoryEnum.equals(sku.getSkuCategory())) {
                result.add(sku);
            }
        }
        return result;
    }

通过商品类型或总价过滤商品

java 复制代码
/**
     * 通过商品类型或总价过滤商品
     * Version: 3.0
     *
     * @param cartSkuList
     * @param categoryEnum
     * @param totalPrice
     * @param categoryOrPrice false:使用价格过滤,true使用分类
     * @return
     */
    public static List<Sku> filterSku(
            List<Sku> cartSkuList,
            SkuCategoryEnum categoryEnum,
            Double totalPrice,
            Boolean categoryOrPrice
    ) {
        List<Sku> result = new ArrayList<Sku>();
        for (Sku s : cartSkuList
        ) {
            if (
                    (categoryOrPrice && categoryEnum.equals(s.getSkuCategory()))
                            || (!categoryOrPrice && s.getTotalPrice() > totalPrice)
            ) {
                result.add(s);
            }
        }
        return result;
    }

根据不同的商品判断标准去过滤商品

实现方式:定义一个函数式接口,然后定义多个实现类,分别对应多个筛选条件.

函数式接口

有且只有一个抽象方法的接口被称为函数式接口 ,函数式接口适用于函数式编程的场景,Lambda就是Java中函数式编程的体现,可以使用Lambda表达式创建一个函数式接口的对象,一定要确保接口中有且只有一个抽象方法,这样Lambda才能顺利的进行推导。

java 复制代码
package lambda.cart;

/**
 * Sku选择谓词接口
 */
public interface SkuPredicate {
    /**
     * 选择判断标准
     * @param sku
     * @return
     */
    boolean test(Sku sku);
}

根据商品是否为图书分类进行筛选

java 复制代码
package lambda.cart;

/**
 * 该商品是否为图书分类
 */
public class SkuBooksCategoryPredicate implements SkuPredicate {
    @Override
    public boolean test(Sku sku) {
        return SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory());
    }
}

根据商品的总价过滤商品

java 复制代码
package lambda.cart;

/**
 * 根据商品的总价过滤商品
 */
public class SkuTotalPricePredicate implements SkuPredicate {
    @Override
    public boolean test(Sku sku) {
        return sku.getTotalPrice() > 2000;
    }
}

需求实现

将函数式接口作为参数传给方法,然后调用函数式接口的test方法.接口有不同的实现类根据传递不同的实现类进行调用.

方法定义

java 复制代码
/**
     * Version: 4.0
     * 根据不同的商品判断标准
     *
     * @param cartSkuList  商品列表
     * @param skuPredicate 不同的商品属性判断标准
     * @return
     */
    public static List<Sku> filterSku(List<Sku> cartSkuList, SkuPredicate skuPredicate) {
        List<Sku> result = new ArrayList<Sku>();
        for (Sku s : cartSkuList
        ) {
            if (skuPredicate.test(s)) {
                result.add(s);
            }
        }
        return result;
    }

实体类的调用方法

java 复制代码
/**
     * 将判断逻辑参数化之实体类
     */
    @Test
    public void filterSku2() {
        List<Sku> cartSkuList = CartService.getCartSkuList();
        List<Sku> skus = CartService.filterSku(cartSkuList, new SkuBooksCategoryPredicate());
        System.out.println(JSON.toJSONString(skus, true));

    }

匿名类的调用方法

java 复制代码
/**
     * 将判断逻辑参数化之 匿名类
     */
    @Test
    public void filterSku3() {
        List<Sku> cartSkuList = CartService.getCartSkuList();
        List<Sku> skus = CartService.filterSku(cartSkuList, new SkuPredicate() {
            @Override
            public boolean test(Sku sku) {
                return sku.getSkuPrice() >= 1000;
            }
        });
        System.out.println(JSON.toJSONString(skus, true));

    }

Lambda方法进行调用

java 复制代码
/**
     * 将判断逻辑参数化之 Lambda
     */
    @Test
    public void filterSku4() {
        List<Sku> cartSkuList = CartService.getCartSkuList();
        List<Sku> skus = CartService.filterSku(cartSkuList, (Sku sku) -> sku.getSkuPrice() >= 1000);
        System.out.println(JSON.toJSONString(skus, true));

    }
相关推荐
Marktowin13 分钟前
Mybatis-Plus更新操作时的一个坑
java·后端
赵文宇36 分钟前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端
程序员爱钓鱼1 小时前
Node.js 编程实战:即时聊天应用 —— WebSocket 实现实时通信
前端·后端·node.js
Libby博仙2 小时前
Spring Boot 条件化注解深度解析
java·spring boot·后端
源代码•宸2 小时前
Golang原理剖析(Map 源码梳理)
经验分享·后端·算法·leetcode·golang·map
小周在成长2 小时前
动态SQL与MyBatis动态SQL最佳实践
后端
瓦尔登湖懒羊羊2 小时前
TCP的自我介绍
后端
小周在成长2 小时前
MyBatis 动态SQL学习
后端
子非鱼9212 小时前
SpringBoot快速上手
java·spring boot·后端
我爱娃哈哈2 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端