函数式编程
需求
有一些商品信息,现在需要将这些商品添加到购物车中获取购物车中的商品信息,然后完成以下需求.
- 找出购物车中所有属于电子数码 的商品
- 根据商品类型查找商品
- 通过商品类型或总价过滤商品
- 根据不同的商品判断标准查找商品
商品实体类
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));
}