This API call返回一个可能很大的List< String>,它没有排序。我需要对它进行排序,搜索和访问随机元素。目前List由ArrayList实现(我检查了源代码),但是在未来的某个未知点,API开发人员可能会选择切换到LinkedList实现(不更改接口)。
对我的程序进行排序,搜索,访问可能很大的LinkedList将是非常缓慢和不可接受的。因此我需要将List转换为ArrayList以确保我的程序的实际效率。但是,由于List很可能已经是ArrayList,因此不必要地创建List的新ArrayList副本是没有效率的。
鉴于这些限制,我提出了以下方法将List转换为ArrayList:
private static <T> ArrayList<T> asArrayList(List<T> list) {
if (list instanceof ArrayList) {
return (ArrayList<T>) (list);
} else {
return new ArrayList<T>(list);
}
}
我的问题是:这是使用未知实现的List的最有效方法吗?有没有更好的方法将List转换为ArrayList?有没有比将List转换为ArrayList更好的选择?
答案 0 :(得分:4)
你不可能比你得到的更简单 - 看起来尽可能高效。
也就是说,这听起来非常像过早优化 - 如果您使用的API的作者更改为LinkedList
,您应该只需要担心这一点。如果你现在担心它,你可能会花费大量的时间和精力来规划未来甚至可能未完成的方案 - 现在是花时间寻找其他问题来解决的问题。大概是你唯一一次改变API的版本是在你自己的应用程序的版本之间 - 在那个时候处理问题,如果有的话。
答案 1 :(得分:2)
正如您所看到的,代码很简单,而且效率很高,因为它只在必要时才创建副本。
所以答案是没有明显更好的选择,除了完全不同类型的解决方案,例如,对你的列表进行排序的东西。
(请记住,很少需要这种级别的优化,所以这不是一个非常常见的问题。)
更新:只是事后的想法,作为一般规则,编写良好的API不会返回不适合它们可能包含的数据量的数据类型。这并不是说你应该盲目相信它们,但这并不是一个完全不合理的假设。
答案 2 :(得分:1)
对我的程序进行排序,搜索,访问可能很大的LinkedList将是非常缓慢和不可接受的。
实际上,它并没有那么糟糕。 IIRC,Collections.sort方法将列表复制到临时数组,对数组进行排序,clear()
原始列表并将数组复制回它。对于足够大的列表,O(NlogN)
排序阶段将主导O(N)
复制阶段。
答案 3 :(得分:0)
支持高效随机访问的Java集合实现了RandomAccess标记接口。对于这样的列表,您可以直接在列表上运行Collections.sort
。对于没有随机访问的列表,您可能应该使用其中一个toArray
方法将列表转储到数组中,对该数组进行排序,然后将其包装到随机访问List
中。
T[] array = (T[])list.toArray(); // just suppress the warning if the compiler worries about unsafe cast
Arrays.sort(array);
List<T> sortedList = Arrays.asList(array);
我认为Arrays.asList
实际上会创建一个ArrayList
,因此如果您愿意,可以尝试投射其结果。
Collections.sort
对所有List
实施都有效,只要它们提供有效的ListIterator
。该方法将列表转储到数组中,对其进行排序,然后使用ListIterator
将值复制回O(n)中的列表。