如何将具有谓词接口的泛型列表转换为 Lambda 表达式?

How to convert Generic List with Predicate Interface into a Lambda Expression?

我正在学习 Java 8 函数式接口并正在尝试一些示例。 我正在尝试创建一种方法,该方法将接受通用列表作为一个参数,将字符串数据过滤器参数作为另一个参数。 下面的代码按预期工作,但是当我尝试将谓词转换为 Lambda 表达式 时,我很挣扎。

@SuppressWarnings("unchecked")
public static <T> List<T> filter_and_find_only_selected_Data1(List<T> genericList, String dataFilter){
    Stream<List<T>> list = genericList.stream().map(eachListObj-> {
            if(eachListObj instanceof Employee){
                return genericList.stream().filter((Predicate<? super T>) new Predicate<Employee>() {
                    public boolean test(Employee eachEmpObj) {
                        return eachEmpObj.getEmpDept().equalsIgnoreCase(dataFilter);
                    }
                }).collect(Collectors.toList());
            }else if(eachListObj instanceof Customer){
                return genericList.stream().filter((Predicate<? super T>) new Predicate<Customer>(){
                    public boolean test(Customer eachCust) {
                        return !eachCust.getCustomerName().equalsIgnoreCase(dataFilter);
                    }
                }).collect(Collectors.toList());
            }
            return null;
    });
    return list.findAny().get();
}

有什么办法,我可以将谓词转换为 Lambda,如果有办法,我可以将 if-else-if 转换为三元运算符。 像:(if 条件)?return 值:(else-if 条件):return value:null;

为什么不全部放入过滤器?试试这个

return genericList.stream().filter(item -> 
                    (item instanceof Customer && ((Customer) item).getCustomerName().equalsIgnoreCase(dataFilter)
                    || (item instanceof Employee && ((Employee) item).getEmpDept().equalsIgnoreCase(dataFilter))))
                    .collect(Collectors.toList());

或为此过滤器提取一个函数

public boolean isAllow(T item, String dataFilter) {
return (item instanceof Customer && ((Customer) item).getCustomerName().equalsIgnoreCase(dataFilter))
                    || (item instanceof Employee && ((Employee) item).getEmpDept().equalsIgnoreCase(dataFilter)))
}
//then use it in filter
return genericList.stream().filter(item -> isAllow(item, dataFilter)
                    .collect(Collectors.toList());

希望对您有所帮助

泛型在这里对您帮助不大,因为 CustomerEmployee 似乎不相互兼容。只要您想使用泛型类型 <T>,您就必须确保此类型在所有方法作用域执行中都是一致的。您所能做的就是使用显式转换。

我将从静态 Map 开始,根据传入的 Class<?> 提取映射函数。只要您想将这些与 dataFilter 进行比较,Function<Object, String> 就会导致 String

static Map<Class<?>, Function<Object, String>> exctractionMap() {
    Map<Class<?>, Function<Object, String>> map = new HashMap<>();
    map.put(Customer.class, item -> Customer.class.cast(item).getCustomerName());
    map.put(Employee.class, item -> Employee.class.cast(item).getEmpDept());
    return map;
}

这张静态地图暂时搁置一会,我想你的整个流可能都被简化了。这应该一起工作:

static List<String> findSelectedData(List<?> genericList, String dataFilter) {
    return genericList.stream()                     // Stream<Object>
        .map(item -> exctractionMap()               // Stream<String> using the function
            .get(item.getClass())                   // ... get through Class<Object>
            .apply(item))                           // ... applied Function<Object,String>
        .filter(s-> s.equalsIgnoreCase(dataFilter)) // Stream<String> equal to dataFilter
        .collect(Collectors.toList());              // List<String>
}

注意:请遵守 Java 约定并将方法命名为 filterAndFindOnlySelectedData1

我想,你其实想要这样的东西:

public static <T> List<T> filter_and_find_only_selected_Data(
    List<T> list, Function<? super T, String> stringProperty, String filterValue) {

    return list.stream()
        .filter(t -> filterValue.equalsIgnoreCase(stringProperty.apply(t)))
        .collect(Collectors.toList());
}

那么,来电者可以使用

List<Employee> source = …;
List<Employee> filtered
    = filter_and_find_only_selected_Data(source, Employee::getEmpDept, "value");

List<Customer> source = …;
List<Customer> filtered
    = filter_and_find_only_selected_Data(source, Customer::getCustomerName, "Bob");

List<File> source = Arrays.asList(new File("foo", "bar"), new File("foo", "test"),
    new File("xyz"), new File("TEST"), new File("abc", "bar"), new File("bla", "Test"));
List<File> filtered = filter_and_find_only_selected_Data(source, File::getName, "test");

展示真正通用方法的灵活性。