Java - 如何避免创建列表然后复制到其中

时间:2014-02-08 20:39:38

标签: java generics arraylist

我有这个通用函数来填充数据库中的对象的ArrayList。问题是我从DB获取一个通用的ArrayList类,然后创建我需要创建的ArrayList的特定子类,然后从通用ArrayList复制到我的子类。我想消除从一个数组复制到另一个数组的不必要的步骤,因为数百行的性能不会很好。如何使用泛型消除该步骤?

因此,要使用更具体的示例,我有一个像

这样的数据类
public class UserData {}

然后是类

public class UserSet extends ArrayList<UserData>

我将使用类似

的函数调用填充UserSet对象
UserSet s = selectAll("SELECT * FROM users", UserSet.class);

和我查询数据库并返回UserSet实例的常规函数​​是这样的。

public static <T, S extends List<T>> S selectAll(String sql, Class<S> listType, Object...args) throws Exception
{
    // t = UserData.class in my example
    Class<T> t = (Class<T>)((ParameterizedType)listType.getGenericSuperclass()).getActualTypeArguments()[0];

    // From Apache's DBUtils project
    QueryRunner run = new QueryRunner();
    // AnnotatedDataRowProcessor is my class that just converts a DB row into a data object
    ResultSetHandler<List<T>> h = new BeanListHandler<T>(t, new AnnotatedDataRowProcessor());

    Connection conn = DB.getConnection();
    try
    {
        // creates the new instance of my specific subclass of ArrayList
        S result = listType.newInstance();
        // returns the ArrayList which I then copy into result
        result.addAll(run.query(conn, sql, h, args));
        return result;
    } 
    finally 
    {
        DbUtils.close(conn);  
    }
}

2 个答案:

答案 0 :(得分:1)

您可以自定义BeanListHandler,如下所示:

ResultSetHandler<List<T>> h = new BeanListHandler<T>(t, new AnnotatedDataRowProcessor()) {
    @Override
    public List<T> handle(ResultSet rs) throws SQLException {
        List<T> rows = listType.newInstance();
        while (rs.next()) {
            rows.add(this.handleRow(rs));
        }
        return rows;
    }
};

你可能需要一些演员来进行编译,但这是一般的想法。

然后调用run.query(conn, sql, h, args)将直接创建您正在寻找的类型。

答案 1 :(得分:0)

我实际上必须将Class类型传递给AnnotatedDataRowProcessor的构造函数,所以我不会破坏这个BeanListHandler中的接口方法。

private Class<?> type;

public <T> AnnotatedDataRowProcessor(Class<T> type)
{
    this.type = type;
}

@Override
public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException
{
    try
    {
        List<T> list = (List<T>)this.type.newInstance();

        while (rs.next())
        {
            list.add(toBean(rs,type));
        }

        return list;
    }
    catch (IllegalAccessException ex)
    {
        throw new SQLException(ex.getMessage());
    }
    catch (InstantiationException ex)
    {
        throw new SQLException(ex.getMessage());
    }
}