我的问题是重复代码。我有如下 4 种方法,但一种用于名称,另一种用于登录等。所以唯一改变的是 setter/getter (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
block 实现一个方法,我怎么能做到这一点?
我的想法是以某种方式告诉方法在 case
block 中使用正确的 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;
}
最佳答案
如果您使用的是 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());
}
关于java - JAVA如何通过参数调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34072197/