You can reduce code size for things like this by using something like Guava, which supplies something resembling functional language style list comprehension.
You can also roll some of this yourself, by defining an interface
public interface Predicate<T> { boolean apply(T obj); }
and then creating a finder method using it:
B findElementByPredicate(Predicate<B> predicate) { for (B b : list) { if (predicate.apply(b)) return b; } return null; }
You can also (as noted in a comment) use reflection to get the value of a field. Implementing the interface defined in arne.b's answer, you can define
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); } }
to make a property extractor that works for a specified field name, and either use that as he described in his answer or make a predicate based on it:
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)); } }
and then use that predicate in the findByPredicate above:
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)); }
If you are only dealing with two properties, all of these tactics will likely increase code size rather than decreasing it. The advantages only happen at greater scale, and you may pay a price in making your code less readable to people unfamiliar with functional style and/or reflection.
for (B i : list)?