环境
Java:1.8
Inteijj IDEA:2019.2
前言
今天在优化代码时,遇到了如题的错误,一下没有反应过来,磋磨了2、3个小时,才悟了过来。
特意做个笔记。
那晚觉没睡好,因为有些细节没想明白~
代码
// 本质上,这个方法就是封装了lambda表达式
public static Predicate<ProductDTO> excludeByMinorCategoryId() {
return productDTO -> {
boolean isConsumable = true;
String hisCategoryName = productDTO.getCategoryName();
Integer minorCategoryId = productDTO.getMinorCategoryId();
if (StringUtils.isNotEmpty(hisCategoryName)) {
if (minorCategoryId == CONSUMABLE_CATEGORY
&& hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
isConsumable = false;
} else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
&& !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
isConsumable = false;
}
}
return isConsumable;
};
}
// 本质上,这个方法就是封装了lambda表达式
public static Predicate<ProductDTO> excludeByMinorCategoryId2(String hisCategoryName, Integer minorCategoryId) {
return productDTO -> {
boolean isConsumable = true;
if (StringUtils.isNotEmpty(hisCategoryName)) {
if (minorCategoryId == CONSUMABLE_CATEGORY
&& hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
isConsumable = false;
} else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
&& !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
isConsumable = false;
}
}
return isConsumable;
};
}
// lambda表达式中具体的实现
// 在使用时,得写上完整的lambda表达式或者使用方法引用
public static boolean excludeByMinorCategoryId3(String hisCategoryName, Integer minorCategoryId) {
boolean isConsumable = true;
if (StringUtils.isNotEmpty(hisCategoryName)) {
if (minorCategoryId == CONSUMABLE_CATEGORY
&& hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
isConsumable = false;
} else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
&& !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
isConsumable = false;
}
}
return isConsumable;
}
我的调用方式如下:
具体使用:
public List<ProductDTO> findExcludeProcess(Integer channelId,
List<Integer> categories,
List<Integer> skuIds,
String keyword) {
return findProduct(channelId, categories, skuIds).stream()
.filter(excludeByMinorCategoryId())
// 错误的写法
.filter(f -> excludeByMinorCategoryId2(f.getCategoryName(), f.getMinorCategoryId()))
.filter(ProductRemoteService::excludeByMinorCategoryId3)
.filter(mixedKeyword(keyword)).collect(Collectors.toList());
}
错误提示如下:
我一直在纠结,为啥:excludeByMinorCategoryId()
调用编译器不报错,
而excludeByMinorCategoryId2()
方法就报错了。
后来,我又再次翻阅《Java8实战》,才明白:
.filter(excludeByMinorCategoryId())
我这种写法使用的是静态辅助方法 的方式来调用的。
我自己写的excludeByMinorCategoryId()
这个方法是个静态方法,会返回Predicate<>
对象。
这个我大概总结下,filter()中的参数即:代码行为参数化
:
① 如下
public class AppleComparator implements Comparator<Apple> {
public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
}
}
inventory.sort(new AppleComparator());
② 使用匿名类
inventory.sort(new Comparator<Apple>() {
public int compare(Apple a1, Apple a2){
return a1.getWeight().compareTo(a2.getWeight());
}
});
③ 使用Lambda 表达式
inventory.sort((Apple a1, Apple a2)
-> a1.getWeight().compareTo(a2.getWeight())
);
④ 静态辅助方法
调用静态辅助方法
让其返回一个Predicate<T>
.filter(excludeByMinorCategoryId())
⑤ 使用方法引用
如下 excludeByMinorCategoryId3
方法
excludeByMinorCategoryId3
代码如下:
// 返回的Boolean
public static boolean excludeByMinorCategoryId3(ProductDTO productDTO) {
boolean isConsumable = true;
String hisCategoryName = productDTO.getCategoryName();
Integer minorCategoryId = productDTO.getMinorCategoryId();
if (StringUtils.isNotEmpty(hisCategoryName)) {
if (minorCategoryId == CONSUMABLE_CATEGORY
&& hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
isConsumable = false;
} else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
&& !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
isConsumable = false;
}
}
return isConsumable;
}
现在回过头来看:
// 写法1
.filter(excludeByMinorCategoryId())
// 写法2 错误写法
.filter(f -> excludeByMinorCategoryId2(
f.getCategoryName(), f.getMinorCategoryId()))
写法2:f -> excludeByMinorCategoryId2(f.getCategoryName(), f.getMinorCategoryId())
本身就是lambda表达式的写法,写完整来,就是:
// 错误写法
.filter(f -> {
return excludeByMinorCategoryId2(
f.getCategoryName(), f.getMinorCategoryId());
})
也就是其必须返回true
或者false
。
那到底
什么时候使用返回值为true
和false
的,
什么时候使用Predicate<T>
的呢?
1、返回值为Predicate<T>
的,说明该方法封装的就是一个lambda
表达式,在filter()
方法中使用,就是普通的方法调用(类似直接传代码的方式,写成静态的就是静态辅助方法)。
2、返回值为Boolean
的,说明该方法得使用方法引用或者补全完整的lambda
表达式才能使用。
总结
行为参数化:
以前:
① 直接传代码
② 匿名类
Java8
③ lambda表达式
④ 静态辅助类
⑤ 方法引用
什么是静态辅助方法
以我的例子来说:
静态方法返回的是:
Predicate<ProductDTO>
即为静态辅助方法
使用时,即为普通的方法调用。
而当返回的是布尔时:
Boolean
即为具体实现。(用lambda
来说的话,就是不包括lambda参数,只有实现部分)
使用时可能需要配合lambda
表达式来使用。