2012-11-18 151 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)。

但是,您可以很容易地看到這不會爲您節省許多代碼行。與此相反的。