我尝试从数组初始化ArrayList,但只是在给定原始数组和子数组开始和结束索引的情况下初始化子数组。
我只能想到做这样的事情来从子阵列创建一个新列表:
Arrays.asList(Arrays.copyOfRange(arr, i, j));
或只是手动将元素添加到列表
List<Integer> result = new ArrayList<>(k);
for (int i = left; i < left + k; i++) {
result.add(arr[i]);
}
这显然不是很漂亮。有没有更好的方法来传递数组和索引?
答案 0 :(得分:7)
“更好”取决于您的要求和用例。由于您建议使用Arrays.asList(...)
,它返回固定大小列表,因此我假设固定大小的列表足以满足您的需求。
可能最快的方法是使用
Arrays.asList(arr).subList(i, j);
这将很快,因为没有元素被复制到任何地方,并且不执行迭代。 Arrays.asList(arr)
本质上创建了一个列表,该列表是原始数组的包装器,subList(...)
创建了一个列表,该列表是现有列表的视图。
权衡(总是存在权衡)是保留对原始数组的引用。因此,如果您生成大量的大型数组,并希望保留每个数组的一小部分,那么从内存消耗的角度来看,这将是一个糟糕的选择。 (相反,如果你有一个大型阵列,并且需要大量不同的切片,可能会重叠,这将是一种非常节省内存的方法,而且速度很快。)
如果内存考虑因素意味着您需要释放对原始数组的任何引用,那么您将被迫以某种方式将元素复制到新结构中。可能最有效的方法是使用您建议的方法:Arrays.copyOfRange(...)
基本上委托给System.arrayCopy(...)
,它基本上是在大多数系统上本地实现的(连续内存块的大量复制),以及然后就像之前Arrays.asList(...)
一样,只为这个新数组创建一个列表包装器。因此,在您要释放对原始数组的引用的场景中,建议使用
Arrays.asList(Arrays.copyOfRange(arr, i, j));
可能是“最好的”方法。