你可以通过使用像Guava这样的东西来减少这样的代码大小,它提供了类似于函数式语言样式列表理解的东西。
您也可以通过定义接口自己滚动其中的一些内容
public interface Predicate<T> {
boolean apply(T obj);
}
然后使用它创建一个查找器方法:
B findElementByPredicate(Predicate<B> predicate) {
for (B b : list) {
if (predicate.apply(b))
return b;
}
return null;
}
您还可以(如评论中所述)使用反射来获取字段的值。实现 arne.b 的答案中定义的接口,您可以定义
public class ReflectivePropertyExtractor<T, P> implements PropertyExtractor<T, P> {
String fieldName;
public ReflectivePropertyExtractor(String fieldName) {
this.fieldName = fieldName;
}
@Override
public P getProperty(T obj) {
try {
Method m = B.class.getMethod(makeAccessorName());
return (P) m.invoke(obj);
} catch (InvocationTargetException e) {
return null;
} catch (NoSuchMethodException e) {
return null;
} catch (IllegalAccessException e) {
return null;
}
}
private String makeAccessorName() {
return "get" + capitalize(fieldName);
}
private String capitalize(String s) {
if ((s == null) || (s.length() == 0))
return s;
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
}
制作一个适用于指定字段名称的属性提取器,并按照他在答案中描述的那样使用它或基于它制作一个谓词:
public class PropertyMatchPredicate<T, P> implements Predicate<T> {
private final P matchValue;
private final PropertyExtractor<T, P> extractor;
public PropertyMatchPredicate(P matchValue, PropertyExtractor<T, P> extractor) {
this.matchValue = matchValue;
this.extractor = extractor;
}
@Override
public boolean apply(T obj) {
return matchValue.equals(extractor.getProperty(obj));
}
}
然后在findByPredicate
上面使用该谓词:
B findElementByProperty(String matchField, final String matchValue) {
final ReflectivePropertyExtractor<B, String> extractor = new ReflectivePropertyExtractor<B, String>(matchField);
return findElementByPredicate(new PropertyMatchPredicate<B, String>(matchValue, extractor));
}
如果您只处理两个属性,所有这些策略都可能会增加而不是减少代码大小。优势只会在更大的范围内出现,并且您可能会付出代价,使不熟悉函数式样式和/或反射的人的代码可读性降低。