如何在接受任何两个对象列表并返回列表的java中编写泛型方法?

时间:2016-09-15 02:08:55

标签: java list generics collections

我有一个域类(DB):

public class PersonDoamin {
private String name;
private String age;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getAge() {
    return age;
}

public void setAge(String age) {
    this.age = age;
}
}

我也有模特课:

public class PersonBean extends PersonDoamin {

}

所以当我转到DAOImpl类并查询List并将此列表传输到List并返回给用户时,因为我有List getAllPerson()的接口方法。所以当我从List传输所有数据时,我的问题就在这里。在这里,我有一些实用方法,可以从一个bean复制到另一个bean:

List<PersonDoamin> list = PersonDAO.getAllPersons();
List<PersonBean> pbList = new ArrayList<PersonBean>();

/* this below logic is pretty much in the all DAO impl*/

for(PersonDoamin p : list){
PersonBean pb = new PersonBean();
CopyHelper.copyBean(p, pb);
pbList.add(pb);
}
return pbList;

我们可以替换循环和复制并添加到另一个列表并使用某种泛型方法返回部分,这将使任何对象两个列表并循环遍历并将其添加到另一个传递的List参数并返回它。像下面这样的东西现在并不完美:

public static <T> List<T> listToArray(List<T> list,List<T> list2) {

    for(T element : list){
        list2.add(element);
    }
    return list2;
}

public static void main(String[] args) {
    List<PersonDoamin> personList = new ArrayList<PersonDoamin>();
    PersonDoamin p = new PersonDoamin();
    p.setName("aj");
    p.setAge("25");
    personList.add(p);
    List<PersonBean> personBeansToReturn = new ArrayList<PersonBean>();
    Test.listToArray(personList , personBeansToReturn );

}

4 个答案:

答案 0 :(得分:1)

有点偏离主题,你的设计似乎有点奇怪,你有“域”类和“Bean”类,并有“Bean”扩展“域”......

无论如何,回到你的问题,你要做的是:

  1. 您有List<Domain>
  2. 您希望将List中的每个域转换为Bean(通过使用某种util方法)
  3. 将生成的Beans放入列表并返回
  4. 让我们一步一步地完成它。

    (顺便说一下,你编写的listToArray方法与原始循环没有对齐,因为它没有进行转换(第2点)。我猜这是错误的?)

    (所有伪代码,因为我手边没有环境来编译它。概念我应该是正确的)

    第1步:Person的方法

    原始util方法的一个最大问题是,将一个Parent对象实例放到一个List of Child中是非法的(应该很容易自己解释原因)。

    util方法应如下所示:

    List<PersonBean> toBeans(List<PersonDomain> domains) {
        List<PersonBean> beans = new ArrayList<>(domains.size());
        for (PersonDomain domain: domains) {
            PersonBean bean = new PersonBean(); 
            CopyHelper.copyBean(domain, bean);
            beans.add(bean);
        }
        return beans;
    }
    

    第2步:使其成为通用

    上述问题是它仅适用于Person。如果你想使它成为通用的,你还需要提供将Domain转换为Bean的函数:

    (假设您使用的是Java8,如果您使用的是旧版本,那么创建自己的界面应该很简单)

    <D,B> List<B> toBeans(List<D> domains, Function<B,D> mapper) {
        List<PersonBean> beans = new ArrayList<>(domains.size());
        for (PersonDomain domain: domains) {
            beans.add(mapper.apply(domain));
        }
        return beans;
    }
    

    以便您可以通过以下方式使用它:

    return toBeans(personDomains, (domain) -> {
                             PersonBean bean = new PersonBean(); 
                             CopyHelper.copyBean(domain, bean);
                             return bean;
                         });
    

    (如果大多数情况下你会使用CopyHelper方式,你可以考虑包装函数)

    <D,B> List<B> toBeansByBeanCopy(List<D> domains, Class<B> beanClass) {
        return toBeans(domains, (domain)-> {
                             B bean = beanClass.newInstance(); 
                             CopyHelper.copyBean(domain, bean);
                             return bean;
                         });
    }
    

    以便您可以将其用作

    return toBeansByBeanCopy(personDomains, PersonBean.class);
    

    第3步:Java已经为您完成了

    实际上你正在尝试做什么,它已经由Java 8中的Java提供了。你可以简单地做:

    return personDomains.stream()
        .map(d -> {
            PersonBean bean = new PersonBean(); 
            CopyHelper.copyBean(domain, bean);
            return bean;
            })
        .collect(Collectors.toList());
    

    如果是标准方式,您可以在lambda表达式中编写一些方法。

    return personDomains.stream()
        .map(BeanMapper.mapper(PersonBean.class))
        .collect(Collectors.toList());
    

    (将实施作为练习)

答案 1 :(得分:1)

如果您正在寻找一种在通用类型上调用new的方法,您可以这样做。您必须使用反射并在newInstance对象上调用Class。我不知道这对你是否可行。

此外,我没有看到任何实际实现bean复制方法而不使用一些重度反射。在下面的例子中,我假装只是转换为所需的类。

public class GenericCopyTest
{

   public static void main( String[] args ) throws Exception
   {
      List<PersonDoamin> personList = new ArrayList<PersonDoamin>();
      PersonDoamin p = new PersonDoamin();
      p.setName( "aj" );
      p.setAge( "25" );
      personList.add( p );
      List<PersonBean> personBeansToReturn = new ArrayList<PersonBean>();
      copyAndDowncast( personList, personBeansToReturn, PersonBean.class );
      System.out.println( personBeansToReturn );
   }

   public static <T,U extends T> List<U> copyAndDowncast( List<T> from, 
           List<U> to, Class<U> type ) 
           throws InstantiationException, IllegalAccessException
   {
      for( T element : from ) {
         U nu = type.newInstance();
         copyBean( element, nu );
         to.add( nu );
      }
      return to;
   }

   private static <X,Y extends X> void copyBean( X from, Y nu ) {
      ((PersonBean)nu).setName( ((PersonDoamin)from).getName() );
      ((PersonBean)nu).setAge( ((PersonDoamin)from).getAge() );
   }

}

class PersonDoamin {
   private String name;
   private String age;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getAge() {
       return age;
   }

   public void setAge(String age) {
       this.age = age;
   }

   @Override
   public String toString()
   {
      return "PersonDoamin{" + "name=" + name + ", age=" + age + '}';
   }

}
class PersonBean extends PersonDoamin {

   @Override
   public String toString()
   {
      return "PersonBean{" + getName() + ',' + getAge()+ '}';
   }

}

输出:

run:
[PersonBean{aj,25}]
BUILD SUCCESSFUL (total time: 0 seconds)

答案 2 :(得分:0)

为什么不使用addAll()呢?它会执行您尝试执行的操作,并且它已经是系统库的一部分。

请记住,您可以将PersonBean添加到PersonDomain列表,但不是相反。

public class GenericCopyTest
{
   public static void main( String[] args ) {
      List<PersonDoamin> personList = new ArrayList<PersonDoamin>();
      List<PersonBean> personBeansToReturn = new ArrayList<PersonBean>();
      personList.addAll( personBeansToReturn );
      personBeansToReturn.addAll( personList );  // <-- FAILS
                                                 // No suitable method found
   }
}

class PersonDoamin {}
class PersonBean extends PersonDoamin {}

答案 3 :(得分:0)

如果要在同一列表中放置多个bean类, 如何使用父类PersonDoamin创建列表,然后,您可以存储PersonDoamin和PersonBean类。

public static void main(String[] args) {
    List<PersonDoamin> personList = new ArrayList<PersonDoamin>();
    PersonDoamin p = new PersonDoamin();
    p.setName("aj");
    p.setAge("25");
    personList.add(p);

    // Changed here. PersonBean => PersonDoamin
    List<PersonDoamin> personBeansToReturn = new ArrayList<PersonDoamin>();

    Test.listToArray(personList, personBeansToReturn);

    // also you can insert PersonBean into the list
    personBeansToReturn.add(new PersonBean());

}