简体   繁体   English

Java 8 数组列表。 哪个更快? 在索引 0 处插入一项或使用一项创建新列表并将所有添加到新列表?

[英]Java 8 ArrayList. Which is it faster? Insert one item at index 0 or create new List with one item and addAll to the new List?

Lets assume I call a third party API and get back a mutable N-many list of objects.让我们假设我调用第三方 API 并返回一个可变的 N 多对象列表。 This list could be as small as 10 objects or as large as a few thousand.该列表可以小到 10 个对象,也可以大到几千个。 I then always want to insert just one object at index 0 of that returned List.然后我总是想在返回的列表的索引 0 处插入一个对象。 I know i can easily call add at index 0 but this is going to be O(n) as it shifts every object for the insert.我知道我可以轻松地在索引 0 处调用 add ,但这将是 O(n),因为它会为插入移动每个对象。 My question is, would it be faster on average (processing wise) to create a new List with the item i plan on inserting at the beginning and then call addAll on that new List passing in the returned 3rd party N-many List?我的问题是,使用我计划在开始时插入的项目创建一个新列表,然后在返回的第 3 方 N 多列表中调用该新列表上的 addAll 平均会更快(处理明智)吗?

It depends on the list implementation.这取决于列表实现。 If you truly have no visibility of what list implementation your third-party has given you, all you can do is empirical testing and benchmarking.如果您真的不了解第三方为您提供的列表实现,您所能做的就是经验测试和基准测试。

More likely, they're returning you one of the standard Java list types, and indeed you've tagged your question arraylist -- is that what you're given?更有可能的是,他们正在返回你的标准Java列表类型中的一种,而事实上你已经标记了问题arraylist -是,你给什么?

ArrayList.add(index,element) uses System.arrayCopy() to copy each shifted element from index n to n+1 , then writes the new element to its slot. ArrayList.add(index,element)使用System.arrayCopy()将每个移动的元素从索引n复制到n+1 ,然后将新元素写入其插槽。 That's O(n), however it's likely to be very fast indeed, since it will use the highly optimised system memmove routine to move whole chunks of RAM at a time.这是 O(n),但它确实可能非常快,因为它将使用高度优化的系统memmove例程一次移动整个 RAM 块。 (see Why are memcpy() and memmove() faster than pointer increments? ). (请参阅为什么 memcpy() 和 memmove() 比指针增量快? )。

In addition, if your extra element nudges the size of the list past the size of the allocated backing array, Java will create a new array and arraycopy the whole lot into there.此外,如果您的额外元素使列表的大小超过分配的后备数组的大小,Java 将创建一个新数组并将整个数组arraycopy到那里。

Bear in mind that you're only copying object references, not whole objects, so for 1000 elements, you're copying (worst case on a 64 bit machine) 64 bits * 1000 == 8 kilobytes of RAM.请记住,您只是在复制对象引用,而不是整个对象,因此对于 1000 个元素,您正在复制(在 64 位机器上的最坏情况)64 位 * 1000 == 8 KB 的 RAM。

Still, for really huge lists, the time it takes might become significant.尽管如此,对于非常庞大的列表,它所花费的时间可能会变得很重要。 Inserting into a linked list is cheaper (should be O(1) at the start or end)插入链表更便宜(在开始或结束时应该是 O(1))

You can make it an O(1) operation on an arbitrary List implementation by writing/finding a List implementation that is just a wrapper around the existing list.您可以通过编写/查找一个 List 实现来使其成为对任意 List 实现的 O(1) 操作,该实现只是现有列表的一个包装器。 For example:例如:

public class HeadedList<T> extends AbstractList<T> {

    private final List tail;

    public HeadedList(T head, List tail) {
       this.head = head;
       this.tail = tail;
    }

    public T get(int index) {
        return index == 0 ? head : tail.get(index - 1);
    }

    public int size() {
        return tail.size() + 1;
    }
}

(NB if you work in languages like Lisp/Clojure/etc you get very used to thinking of lists in this way) (注意,如果您使用 Lisp/Clojure/etc 等语言工作,您会非常习惯以这种方式思考列表)

But, only bother with this if benchmarking reveals that real performance problems are being caused by list building.但是,只有在基准测试显示真正的性能问题是由列表构建引起的时候才需要考虑这个问题。

If the returned List impl is ArrayList, both options are the same: O(n).如果返回的 List impl 是 ArrayList,则两个选项相同:O(n)。
If the returned impl is LinkedList, inserting at head is O(1).如果返回的 impl 是 LinkedList,则在头部插入是 O(1)。

There is an always O(1) option: Create a List wrapper class that is backed by the returned list but allows insertion at head by storing the inserted element internally.总是有一个 O(1) 选项:创建一个 List 包装类,它由返回的列表支持,但允许通过在内部存储插入的元素在头部插入。 You would have to create a custom iterator to iterate over the inserted elemdnt then delegate to the list.您必须创建一个自定义迭代器来迭代插入的元素,然后委托给列表。 Most methods would need similar customisation.大多数方法都需要类似的定制。

If it's only a 1000 or so elements I wouldn't bother, unless your application is complete and you've determined there is a measurable and severe enough performance problem at this operation.如果它只有 1000 个左右的元素,我不会打扰,除非您的应用程序是完整的,并且您已经确定在此操作中存在可衡量且足够严重的性能问题。

If you were inserting multiple elements at head, then you would take a hit once to create a LinkedList, then each insertion would be O(1), but since you only have 1 to insert, don't bother.如果您在头部插入多个元素,那么您需要点击一次以创建一个 LinkedList,然后每次插入都是 O(1),但由于您只有 1 个要插入,所以不要打扰。

KISS: Just insert the element into the returned list. KISS:只需将元素插入返回的列表中。 I'm sure it will be faster enough, and most likely way faster than the library anyway.我相信它会足够快,而且很可能比图书馆快得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JMH - List#addAll 比 ArrayList#new 快吗? - JMH - List#addAll faster than ArrayList#new? 使用Arraylist addAll()创建具有不同引用的新对象的新列表 - Using Arraylist addAll() to create a new list with new objects with different reference 如果第二个列表的一项满足条件并返回新列表,则 Java 8 foreach 添加到新列表 - Java 8 foreach add to new list if one item of the second list fulfill condition and return a new list 将项目从一个列表/阵列列表移动到另一列表/阵列列表 - Move an item from one list/arraylist to another list/arraylist 用于内容复制的ArrayList.addAll(list)与新ArrayList &lt;&gt;(list)之间的区别 - Difference between ArrayList.addAll(list) and new ArrayList<>(list) for content copying Java addAll(集合)与新的ArrayList(集合) - Java addAll(collection) vs new ArrayList(collection) 如果我在复制的 ArrayList 中更改某些内容,则会更改原始 ArrayList 值。 即使我使用了列表<employee> empCopy=new ArrayList(原始列表)</employee> - Original ArrayList values Changed if i change something in Copied ArrayList. Even though i used List<Employee> empCopy=new ArrayList(origialList) 列表中的一种类型的项目 - One type of item in list Java-从ResponseEntity列表中获取一项 - Java - Get one item from ResponseEntity List 检查Java列表并根据某些条件创建一个新列表 - Check a Java list and create a new one according to some criteria
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM