将List <! - ? - >转换为List <objecttype> </objecttype>的最快方法

时间:2009-08-06 04:06:18

标签: java generics optimization list

这是一个Java问题。

List<?>转换为List<ObjectType>的最快方法是什么?我知道通过迭代可以做到这一点,请排除该选项。

迭代示例,

final List<ObjectType> targetList = new ArrayList<ObjectType>();
// API returns List<?> so I have no choice.
List<?> resultList = resultSet.getResults(); 

// This is slow. Average list size is 500,000 elements.
while (resultList != null && !resultList.isEmpty()) {
    for (final Object object : resultList) {
        final ObjectType objectType = (ObjectType) object;
        targetList.add(objectType);
    }
    resultSet = someService.getNext(resultSet);
    resultList = resultSet.getList();
}

感谢。

5 个答案:

答案 0 :(得分:5)

这有点可怕但是根据上下文,你可能只是通过施放而逃脱:

final List<ObjectType> targetList = (List<ObjectType>)problemSolver.getResults(); 

答案 1 :(得分:2)

正如汤姆上面所说,如果您知道原始List<?>中的所有内容都是ObjectType的事实 - 正如迭代代码所暗示的那样 - 转换为List<ObjectType>将会有效很好。

与迭代代码的唯一区别在于,如果任何内容 ObjectType,在迭代代码中ClassCastException将在您填充{{1}时发生在直接演员的情况下,当你获得价值时,它就会发生。 E.g:

targetList

打印

public static void main(String[] args) {
    List<?> list = Arrays.<Object> asList('I', "am", "not", "homogeneous");
    List<Character> targetList = (List<Character>) list;

    int index = 0;
    try {
        for (Character c : targetList) {
            System.out.println(c);
            index++;
        }
    } finally {
        System.out.println("Reached " + index);
    }
}

答案 2 :(得分:1)

嗯......如果你真的在处理500,000个元素并解决性能问题,我会咬紧牙关(子弹是编译器的“未选中”警告)并投下它:

List<ObjectType> targetList = new ArrayList<ObjectType>((List<ObjectType>) resultList);

然后,您可以使用@SuppressWarnings(“unchecked”)注释来禁止警告。

当然,上面假设resultList不能以某种方式满足你(也许它是不可修改的或阵列支持的或者你有什么)。否则你可以简单地施放它。

答案 3 :(得分:1)

正确的解决方案取决于您是否要确保放入targetList的元素确实是ObjectType(或子类型)的实例。

如果你不在乎,有一个不安全的类型转换的解决方案就可以了。除非你需要复制,否则@Toms解决方案会更好。 (如果getResults()返回链接列表,您可能需要复制,并且您的算法需要经常使用targetList.get(int)。)但要注意,如果您的假设是,您可能会在以后遇到意外的ClassCastException不正确。

如果您需要确保没有错误类型的元素,那么您必须使用基于迭代器的解决方案,除非您知道List为您提供的getResults()类型。 (如果您可以将getResults()的结果转换为ArrayList,则使用get(int)建立索引应该比使用Iterator更快。另一方面,如果结果是LinkedList,然后使用get(int)复制列表O(N**2) !!)

这个怎么样?

final List<?> resultList = problemSolver.getResults(); 

List<ObjectType> targetList;
if (resultList == null || resultList.isEmpty()) {
    targetList = Collections.empyList();
} else {
    int len = resultList.size();
    // it is important to preallocate the ArrayList with the
    // right size ... to conserve space and avoid copy on realloc
    // of the list's private backing array.
    targetList = new ArrayList<ObjectType>(len);
    if (resultList instanceof ArrayList) {
        // Copy using indexing - O(N) for ArrayLists
        ArrayList<?> arrayList = (ArrayList) resultList;
        for (int i = 0; i < len; i++) {
            targetList.add((ObjectType) (arrayList.get(i)));
        }
    } else {
        // Copy using iterator - O(N) for all sane List implementations,
        // but with a larger C than the best case for indexing.
        for (Object obj : resultList) {
            targetList.add((ObjectType) obj);
        }
    }
}

答案 4 :(得分:0)

迭代有什么问题?

但是如你所愿:

final List<?> src = ...;
final int len = src.size();
final SomeType[] dstArray = new SomeType[len];
src.<SomeType>toArray(dstArray);
final List<SomeType> dst = java.util.Arrays.asList(dstArray);

或者:

(免责声明:与编译完全不同。)

我更喜欢迭代方法。