Kotlin中使用Predicate谓词实现列表动态过滤
问题原因
你遇到的类型不匹配错误根源是Kotlin集合的filter扩展函数要求传入参数类型为(T) -> Boolean的判断函数:即遍历每个元素时,传入元素、得到布尔类型的判断结果。
你写的myList.filter { buildDatePredicate(...) }中,外层大括号包裹的内容是一个lambda,这个lambda执行后直接返回了Predicate<MyClass>类型的对象,没有将当前遍历的列表元素传入谓词执行判断,编译器期望拿到Boolean结果,实际拿到了Predicate实例,因此报错。
实现方案
你要的动态谓词过滤效果完全可以实现,有两种常用写法:
- 保留现有Java风格
Predicate返回值的写法:调用谓词的test()方法执行判断,建议提前生成谓词实例,避免遍历列表时重复创建对象:
// 提前构造好匹配规则 val dateMatchRule = buildDatePredicate(fromDate.toLocalDate(), toDate.toLocalDate()) // 遍历元素时传入谓词做判断 val filteredList = myList.filter { dateMatchRule.test(it) }
- 适配Kotlin惯用写法:将
buildDatePredicate的返回值改为Kotlin原生函数类型(MyClass) -> Boolean,无需额外调用test方法,可以直接传入filter使用:
首先修改谓词构造函数:
fun buildDatePredicate(dateFrom: LocalDate?, dateTo: LocalDate?): (MyClass) -> Boolean { if (dateFrom != null && dateTo == null) { return { myItem -> myItem.date.isAfter(dateFrom) } } if (dateTo != null && dateFrom == null) { return { myItem -> myItem.date.isBefore(dateTo) } } if (dateTo != null && dateFrom != null) { return { myItem -> myItem.date.isBefore(dateTo) && myItem.date.isAfter(dateFrom) } } // 无日期参数时不过滤,返回全匹配 return { true } }
过滤时直接传入构造好的函数即可,注意不要额外套一层大括号,否则会再次出现类型不匹配问题:
val filteredList = myList.filter(buildDatePredicate(fromDate.toLocalDate(), toDate.toLocalDate()))
补充提示:你当前的日期判断逻辑用了
isAfter和isBefore,是不包含传入的起止日期边界的,如果需要包含边界,可以替换为!isBefore(大于等于)和!isAfter(小于等于)。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

