这是一个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();
}
感谢。
答案 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)
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);
或者:
(免责声明:与编译完全不同。)
我更喜欢迭代方法。