如何创建创建列表的方法的通用版本

时间:2012-11-18 19:29:18

标签: java generics

是否可以将以下功能创建为可以重复使用的通用功能?

我想传入一个集合,并返回对象中特定属性的列表。

到目前为止,我有这个例子:

   private List<Integer> getPropertyABCIdsFromSomeObject(List<SomeObject> someObjects) {
        List<Integer> ids = new ArrayList<Integer>();
        for(SomeObject so : someObjects) {
            ids.add(so.getPropertyABCId());
        }
        return ids;
    }

因此,此方法仅适用于SomeObject类型,并返回PropertyABCId列表。

现在,如果我想要一个其他属性的列表,我必须复制这个函数,只需要很少的更改。

仿制药可以在这里挽救这一天吗?

2 个答案:

答案 0 :(得分:3)

你需要一个界面,但是:

interface HasProperty<T> {
    T getProperty();
}

public static <T> List<T> getProperties(List<? extends HasProperty<T>> items) {
    List<T> properties = new ArrayList<T>();
    for (HasProperty<T> item : items) {
        properties.add(item.getProperty());
    }
    return properties;
}

答案 1 :(得分:2)

基于模板的解决方案

定义这样的模板:

public class ConvertListTemplate<A, B>
{
  public List<B> convert( List<A> list ) {
    List<B> result = new ArrayList<B>();
    for( A a : list ) {
      result.add(convertElement(a));
    }
    return result;
  }

  public abstract B convertElement(A element);
}

然后在您的代码中执行此操作:

List<Integer> result = new ConvertListTemplate<SomeObject, Integer>() {
  public Integer convertElement(SomeObject element) {
    return element.getPropertyABCId();
  }
}.convert(source);

基于策略的解决方案

使用这样的方法:

public <A, B> List<B> getProperties(
        List<A> list,
        GetPropertyStrategy<? super A, ? extends B> strategy
) {
  List<B> result = new ArrayList<B>();
  for( A a : list ) {
    result.add(strategy.getProperty(a));
  }
  return result;
}

使用策略界面:

public interface GetPropertyStrategy<A, B>
{
  public B getProperty(A toConvert);
}

然后调用这样的方法:

List<Integer> result = getProperties(source, new GetPropertyStrategy<SomeObject, Integer>() {
  public Integer getProperty(SomeObject element) {
    return element.getPropertyABCId();
  }
});