繁体   English   中英

Java 流过滤器内的反射

[英]Java reflection inside stream's filter

我有一个 Java POJO:

public class Event {
    private String id;
    private String name;
    private Long time;
}

我创建的一个简单的过滤方法是:

public static List<Event> simpleFilter(List<Event> eventList, String value) {
    return eventList.stream().filter(Event -> Event.getName().equals(value)).collect(Collectors.toList());
}

现在我的任务是创建一个通用方法而不是simpleFilter ,它可以应用于任何 Java POJO object 及其任何字段。 For example, if in future there is a new Java object Employee and we want to filter on its String field employeeDepartment , we can use same generic filter method by passing the List of Java object ( List<Employee> , Class type Employee.class ,我们要过滤哪个字段 ( getEmployeeDepartment ) 和什么值 ( "Computer" )。

我创建了一个方法定义:

public static <T> List<T> genericStringFilterOnList(List<T> list, Class<T> c, String methodName, String value) {
}

来电者看起来像:

//events is List<Event>
//getName is the method in Event on which I want to filter
//e2 is value which I want to filter
genericStringFilterOnList(events, Event.class, "getName", "e2")

我的实现是:

public static <T> List<T> genericStringFilterOnList(List<T> list, Class<T> c, String methodName, String value) {
    return list.stream().filter(m -> {
        try {
            return c.getMethod(methodName, null).invoke(c).equals(value);
        } catch (IllegalAccessException e) {
        } catch (IllegalArgumentException e) {
        } catch (InvocationTargetException e) {
        } catch (NoSuchMethodException e) {
        } catch (SecurityException e) {
        }
        return false;
    }).collect(Collectors.toList());
}

由于检查异常,所有这些捕获都是由 IDE 生成的。 这似乎不起作用,因为它返回一个空列表。 我在这里尝试做的是 - 使用 class 类型(即Event.class ),我使用反射获取方法名称,然后调用该方法,然后调用它基本上是调用事件 ZA2F2ED4F8EBC2CBB4C21 的getName()方法,然后等于. 我也试过这个 -

return c.getMethod(methodName, null).invoke(c.newInstance()).equals(value);

但是有了这个我得到了NPE

}).collect(Collectors.toList());

您能帮我创建一个通用方法,该方法可以为任何 POJO 的列表调用,并且过滤器可以应用于其任何 String 类型的方法吗?

调用应该发生在蒸过的项目上,而不是 class 本身。 方法Method::invoke(Object obj, Object... args)有两个参数:

  • obj - 调用底层方法的 object
  • args - 用于方法调用的 arguments

换行:

return c.getMethod(methodName, null).invoke(c).equals(value);

.. 至:

return c.getMethod(methodName, null).invoke(m).equals(value);

混淆来自单字母变量名称(请参阅下面的解决方案)。


整个解决方案将被简化。 您不想通过反射为 stream 管道中存在的每个 object 提取相同的Method 首先提取Method并重用它:

static <T> List<T> genericStringFilterOnList(List<T> list, Class<T> clazz, String method, String value) {
    try {
        // reflection invoked just once
        Method method = clazz.getMethod(method, null);
        // now streaming of the n items
        return list.stream().filter(item -> {
            try { 
                return value.equals(method.invoke(item));
            } catch (IllegalAccessException | InvocationTargetException e) {}
            return false;
        }).collect(Collectors.toList());
    } catch (NoSuchMethodException e) {}
    return Collections.emptyList();
}

(在此问题的 scope 中):请注意,调用的方法返回null的概率高于传递的value ,因此我会选择 go for value.equals(method.invoke(item)) 也许,当两个值都是要比较的null时,您想添加一些额外的比较条件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM