2012-11-18 155 views
0


我有以下情况。我有一些A类,它有B类对象列表。 B类有两个X,Y类型的字符串和两个getter getX()getY()。 我想在类A中有一个方法,从给定值的字符串选择的B对象的集合中返回一个对象。例如:通过对象属性值查找

B findElementByX(String x) { 
    for (B i : list) { 
     if (i.getX().equals(x) 
      return i; 
    } 
    return null; 
} 

对于其它参数Y我将具有几乎相同的代码,BTU代替的getX(),会有的getY()。对我来说,它不必要的代码冗余。我的问题是:如何编写此方法以便通过X或Y属性值查找一种方法?这是在Java中解决这个问题的通用方法吗?

+0

不应该是'for(B i:list)'? –

+0

根据你的问题,X和Y都是相同类型的字符串。如何将泛型应用于同一类型。但可以通过反思来完成。我猜的数据类型也是B。 –

回答

1

您可以使用类似Guava的东西来减少代码大小,例如提供类似于功能语言风格列表理解的东西。

您也可以推出一些这方面自己的,通过定义一个接口

public interface Predicate<T> { 
    boolean apply(T obj); 
} 

,然后创建一个finder方法使用它:

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)); 
} 

如果你只处理两个属性,所有这些TAC的抽动可能会增加代码的大小,而不是减少它。优势只在更大的规模上才会发生,并且您可能会付出代价,使您的代码对不熟悉功能风格和/或反射的人员不易读取。

0

传递X或Y作为另一个参数来查找getX()或getY()else返回null。

B findElementByXY(String s,String identifier) { 
    for (X i : list) 
    { 
     if ("X".equals(identifier)&&i.getX().equals(s)) 
      return i; 
     else if ("Y".equals(identifier)&&i.getY().equals(s)) 
      return i; 

    } 
    return null; 
} 
3

你可以有一个功能

B findElementByProperty(String prop, PropertyExtractor<B,String> propEx) 

其中PropertyExtractor<B,P>是一个通用的函数指针的B返回类型P的功能。

只是说Java没有函数指针。因此,PropertyExtractor<B,P>可以改为与单一方法的接口,如P getProperty(B obj),其中您当然需要两个实现(分别打包电话getXgetY)。

但是,您可以很容易地看到这不会为您节省许多代码行。与此相反的。