Java 转换列表的最快方法<&燃气轮机;列出<;ObjectType>;

Java 转换列表的最快方法<&燃气轮机;列出<;ObjectType>;,java,generics,optimization,list,Java,Generics,Optimization,List,这是一个Java问题 将列表转换为列表的最快方法是什么?我知道这是通过迭代实现的,请排除该选项 以迭代为例 final List<ObjectType> targetList = new ArrayList<ObjectType>(); // API returns List<?> so I have no choice. List<?> resultList = resultSet.getResults(); // This is slow.

这是一个Java问题

列表
转换为
列表
的最快方法是什么?我知道这是通过迭代实现的,请排除该选项

以迭代为例

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();
}
final List targetList=new ArrayList();
//API返回列表,所以我别无选择。
List resultList=resultSet.getResults();
//这太慢了。平均列表大小为500000个元素。
while(resultList!=null&&!resultList.isEmpty()){
for(最终对象:结果列表){
最终ObjectType ObjectType=(ObjectType)对象;
add(objectType);
}
resultSet=someService.getNext(resultSet);
resultList=resultSet.getList();
}

谢谢。

嗯。。。如果你真的要处理500000个元素,并且表现出性能问题,我会咬紧牙关(子弹是编译器的“未检查”警告)并抛出它:

List<ObjectType> targetList = new ArrayList<ObjectType>((List<ObjectType>) resultList);
List targetList=new ArrayList((List)resultList);
然后可以使用@SuppressWarnings(“未选中”)注释来抑制警告


当然,以上假设
resultList
在某种程度上不能满足您的要求(可能是不可修改的,或者是支持数组的,或者是您所拥有的)。否则,你可以简单地施放它。

这有点可怕,但根据上下文的不同,你可能不需要施放:

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

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

如果你不在乎,其中一个带有不安全类型转换的解决方案就可以了。除非您需要复制,@Toms解决方案更好。(如果
getResults()
返回一个链表,并且您的算法需要大量使用
targetList.get(int)
,您可能需要进行复制。)但请注意,如果您的假设不正确,以后可能会出现意外的
ClassCastException

如果需要确保没有错误类型的元素,则必须使用基于迭代器的解决方案,除非您知道
getResults()
提供的
List
类型。(如果您可以将
getResults()
的结果强制转换为
ArrayList
,那么使用
get(int)
进行索引应该比使用
迭代器
更快。另一方面,如果结果是
链接列表
,则使用
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);
        }
    }
}
final List resultList=problemSolver.getResults();
列出目标清单;
if(resultList==null | | resultList.isEmpty()){
targetList=Collections.empyList();
}否则{
int len=resultList.size();
//使用
//大小合适…以节省空间并避免在realloc上复制
//列表的专用支持数组的。
targetList=新阵列列表(len);
if(结果列表实例为ArrayList){
//对ArrayList使用索引-O(N)进行复制
ArrayList ArrayList=(ArrayList)结果列表;
对于(int i=0;i
迭代有什么问题

但如你所愿:

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);
最终列表src=。。。;
final int len=src.size();
final SomeType[]dstArray=新SomeType[len];
src.toArray(DST阵列);
最终列表dst=java.util.Arrays.asList(dstArray);
或:

(免责声明:与其说是编译的,不如说是编译的。)


我更喜欢迭代法。

正如Tom在上面所说的,如果您知道原始
列表中的所有内容都是
对象类型
——正如迭代代码所暗示的那样——转换到
列表
会很好

与迭代代码的唯一区别在于,如果任何东西不是
对象类型
,则在迭代代码中,当您填充
目标列表
时,将发生
ClassCastException
,而使用直式转换时,将在您获取值时发生。例如:

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);
    }
}

由于您使用的是基于数组的列表,您是否尝试过预分配500000个元素(或者大约为500000个)。这可能会提高性能。现在我想一想,LinkedList可以完全消除整个“预分配内存”问题。是否有什么东西可以从
resultList
中删除元素,或者是
应该是
if
?@Laurence Gonsalves,好问题,我已经修改了代码。谢谢。
LinkedList
应该慢一点。你会不必要地使用大量内存。对于这个问题,我也会采用这种解决方案。一般来说,这不是类型安全的。我采用这种方法,尽管我将其隐藏在Lists.cast()实用程序方法后面,这样你实际上就不需要告诉RHS列表中有哪些类型(无论如何,大多数情况下)。嗯。。。
src.toArray()不创建副本吗?是的,虽然这不应该是一个大问题(仍然比
LinkedList
!)要好)。我忘记了带参数的
toArray
有奇怪的界限。
I
Exception in thread "main" java.lang.ClassCastException: java.lang.String 
cannot be cast to java.lang.Character
    at Foo.main(Foo.java:100)
Reached 1