【问题标题】:How to convert Generic List with Predicate Interface into a Lambda Expression?如何将带有谓词接口的通用列表转换为 Lambda 表达式?
【发布时间】:2020-09-11 20:18:59
【问题描述】:

我正在学习 Java 8 功能接口并尝试了一些示例。 我正在尝试创建一种方法,该方法将接受通用列表作为一个参数,并将字符串数据过滤器参数作为另一个参数。 下面的代码按预期工作,但是当我尝试将 Predicate 转换为 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 condition)?return Value:(else-if condition):return value:null;

【问题讨论】:

  • 接受任意T 的“通用”方法没有多大意义,但只有当T 实际上是两个不相关的具体类型之一时才会做一些有用的事情。

标签: java-8 predicate


【解决方案1】:

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

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");

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

【讨论】:

    【解决方案2】:

    为什么不把所有的都放在过滤器里?试试这个

    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());
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      泛型在这里对您没有多大帮助,因为CustomerEmployee 似乎不兼容。只要您想使用泛型类型&lt;T&gt;,您就必须确保此类型在所有方法范围执行中是一致的。您所能做的就是使用显式强制转换。

      我将从静态Map 开始,根据传入的Class&lt;?&gt; 提取映射函数。 Function&lt;Object, String&gt; 的结果是 String,只要您希望将它们与 dataFilter 进行比较:

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多