前言:我们假设有这样一个场景,一个电商订单中,有各种优惠券促销活动,比如一个订单有用了店铺优惠券(减100),商品优惠券(减50),满减优惠券(减35),当然优惠券可以叠加,比如这个单有用了两张店铺优惠券,我们需要统计某类优惠券共减去多少金额,处理成一个Map集合,Map集合的键key是优惠券名称,值value是金额。
本文涉及的代码在github上,点击 链接 可查看源码。
public class Coupon {
/**
* 优惠券名称
*/
private String name;
/**
* 优惠券金额
*/
private BigDecimal amount;
}
我们假设订单中的优惠券信息如下:
{
"couponList":[
{
"店铺优惠券":100
},
{
"商品优惠券":50
},
{
"店铺优惠券":100
},
{
"满减优惠券":35
}
]
}
这里简单地写一个方法来表示订单中的优惠券金额集(请忽略魔法值),方法返回一个Coupon优惠券集合:
private static List couponList() {
Coupon coupon1 = new Coupon("店铺优惠券", new BigDecimal("100"));
Coupon coupon2 = new Coupon("商品优惠券", new BigDecimal("50"));
Coupon coupon3 = new Coupon("店铺优惠券", new BigDecimal("100"));
Coupon coupon4 = new Coupon("满减优惠券", new BigDecimal("35"));
List couponList = new ArrayList<>(4);
couponList.add(coupon1);
couponList.add(coupon2);
couponList.add(coupon3);
couponList.add(coupon4);
return couponList;
}
我们所需要最终的结果是这样子的:
{店铺优惠券=200,商品优惠券=50, 满减优惠券=35 }
private static Map cumulative1(List coupons) {
//key name,value cumulative price
Map couponMap = new HashMap<>(5);
coupons.forEach(coupon -> {
String nameKey = coupon.getName();
BigDecimal amountValue = coupon.getAmount();
if (couponMap.containsKey(nameKey)) {
couponMap.put(nameKey, couponMap.get(nameKey).add(amountValue));
} else {
couponMap.put(nameKey, amountValue);
}
});
return couponMap;
}
private static Map cumulative2(List coupons) {
//key name,value cumulative price
Map couponMap = new HashMap<>(5);
coupons.forEach(coupon -> {
String nameKey = coupon.getName();
BigDecimal amountValue = coupon.getAmount();
couponMap.put(nameKey, couponMap.get(nameKey) == null ? amountValue : couponMap.get(nameKey).add(amountValue));
});
return couponMap;
}
private static Map cumulativeByLambda(List coupons) {
//key name,value cumulative price
Map couponMap = new HashMap<>(5);
coupons.forEach(coupon -> {
String nameKey = coupon.getName();
BigDecimal amountValue = coupon.getAmount();
couponMap.merge(nameKey, amountValue, (oldValue, newValue) -> oldValue.add(newValue));
});
return couponMap;
}
这里Map集合的merge方法是Java8新增的一个默认方法,方法有三个参数,第一个参数是key,第二个参数是value,而第三个参数针对函数式接口的一个实现,merge方法帮我们写了如果map集合无该key的话,就存放value,如果map集合已经存在该key了,那么具体要怎么存放新的value,由你来实现,这里留了一个BiFunction
private static Map cumulativeByLambda(List coupons) {
//key name,value cumulative price
Map couponMap = new HashMap<>(5);
coupons.forEach(coupon -> {
String nameKey = coupon.getName();
BigDecimal amountValue = coupon.getAmount();
couponMap.merge(nameKey, amountValue, BigDecimal::add);
});
return couponMap;
}
我们点进去merge方法里面,看看源码:
public interface Map {
default V merge(K key, V value,
BiFunction super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
}
我们可以看到,这里关键之处在于merge方法的第三个参数,给我们留了一个函数式接口BiFunction
@FunctionalInterface
public interface BiFunction {
R apply(T t, U u);
}
apply方法待实现,方法参数是泛型类T和U,返回参数是泛型类R,简而言之就是我们需要实现一个方法,方法传入T和U,方法R。
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
public interface Map {
default V merge(K key, V value,
BiFunction super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
}
本文仅记录下学习过程中的一些收获,如有不足之处,请指正或者提出好的建议。◕‿◕。谢谢。