我的问题是双重代码。我有4个方法,如下面,但一个用于Name,另一个用于登录等。所以唯一改变的是getters(p.getName(),p.getLogin()...)。
private Set<Person> filterByName(Set<String> values, Set<Person> peeps){
Set<Person> filtered = new HashSet<>();
for (Person p : peeps){
if(isIn(p.getName(), values)){
filtered.add(p);
}
}
return filtered;
}
我在switch中调用这些方法:
switch(var){
case NAME:
filtered = filterByName(arg1, arg2);
case ...
如果不为每个case
块实现方法,我该怎么做?
我的想法是以某种方式告诉方法在case
块中使用正确的getter,因此只有一种方法可用于所有过滤,例如
private Set<Person> universalFilter(Set<String> values, Set<Person> peeps) {
Set<Person> filtered = new HashSet<>();
for (Person p : peeps){
if(isIn(***SOMETHING CLEVER***, values)){
filtered.add(p);
}
}
return filtered;
}
答案 0 :(得分:3)
如果您使用的是Java 8,则可以使用方法引用来完全按照您的意愿执行操作。最小的变化是使用Function
对象。您的filterByName
方法需要一个额外的参数,将每个Person
对象映射到您要测试的属性:
private Set<Person> filter(Function<Person,String> filter, Set<String> values, Set<Person> peeps) {
Set<Person> filtered = new HashSet<>();
for (Person p : peeps){
if(isIn(filter.apply(p), values)){
filtered.add(p);
}
}
return filtered;
}
然后按如下方式调用方法:
filter(Person::getName, values, peeps);
如果要允许更复杂的过滤器,可以将整个过滤器指定为谓词:
private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
Set<Person> filtered = new HashSet<>();
for (Person p : peeps){
if (filter.test(p)){
filtered.add(p);
}
}
return filtered;
}
可以通过以下方式调用:
filter(p -> isIn(p.getName(), values), peeps);
实际上,Java 8通过removeIf
方法在运行时库中提供了过滤功能:
private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
Set<Person> filtered = new HashSet<>();
filtered.removeIf(filter);
return filtered;
}
或使用流:
private Set<Person> filter(Predicate<Person,String> filter, Set<Person> peeps) {
return peeps.stream().filter(filter).collect(Collectors.toSet());
}
答案 1 :(得分:1)
一种简单的方法是使用switch变量作为参数传入Person上的新方法get()。
if(isIn(p.get(var), values)){
然后在Person中实现新方法,例如:
public void get(String var) {
if (var.equals("NAME")) return name;
...
}
答案 2 :(得分:0)
您可以传递另一个String参数,该参数是您想要过滤的变量(“名称”,“登录”...)
然后通过反射,您可以找到并调用相关的 getter 方法:
Method method = Person.class.getMethod("get"+ filter, null);
String returnValue = (String)(method.invoke(p, null));
if(isIn(returnValue , values))
...