Why is ArrayDeque better than LinkedList - java

I am trying to to understand why Java's ArrayDeque is better than Java's LinkedList as they both implement Deque interface.
I hardly see someone using ArrayDeque in their code. If someone sheds more light into how ArrayDeque is implemented, it would be helpful.
If I understand it, I will be more confident using it. I could not clearly understand the JDK implementation as to the way it manages head and tail references.

Linked structures are possibly the worst structure to iterate with a cache miss on each element. On top of it they consume way more memory.
If you need add/remove of the both ends, ArrayDeque is significantly better than a linked list. Random access each element is also O(1) for a cyclic queue.
The only better operation of a linked list is removing the current element during iteration.

I believe that the main performance bottleneck in LinkedList is the fact that whenever you push to any end of the deque, behind the scene the implementation allocates a new linked list node, which essentially involves JVM/OS, and that's expensive. Also, whenever you pop from any end, the internal nodes of LinkedList become eligible for garbage collection and that's more work behind the scene.
Also, since the linked list nodes are allocated here and there, usage of CPU cache won't provide much benefit.
If it might be of interest, I have a proof that adding (appending) an element to ArrayList or ArrayDeque runs in amortized constant time; refer to this.

All the people criticizing a LinkedList, think about every other guy that has been using List in Java probably uses ArrayList and an LinkedList most of the times because they have been before Java 6 and because those are the ones being taught as a start in most books.
But, that doesn't mean, I would blindly take LinkedList's or ArrayDeque's side. If you want to know, take a look at the below benchmark done by Brian (archived).
The test setup considers:
Each test object is a 500 character String. Each String is a different object in memory.
The size of the test array will be varied during the tests.
For each array size/Queue-implementation combination, 100 tests are run and average time-per-test is calculated.
Each tests consists of filling each queue with all objects, then removing them all.
Measure time in terms of milliseconds.
Test Result:
Below 10,000 elements, both LinkedList and ArrayDeque tests averaged at a sub 1 ms level.
As the sets of data get larger, the differences between the ArrayDeque and LinkedList average test time gets larger.
At the test size of 9,900,000 elements, the LinkedList approach took ~165% longer than the ArrayDeque approach.
Graph:
Takeaway:
If your requirement is storing 100 or 200 elements, it wouldn't make
much of a difference using either of the Queues.
However, if you are developing on mobile, you may want to use an
ArrayList or ArrayDeque with a good guess of maximum capacity
that the list may be required to be because of strict memory constraint.
A lot of code exists, written using a LinkedList so tread carefully when deciding to use a ArrayDeque especially because it DOESN'T implement the List interface(I think that's reason big enough). It may be that your codebase talks to the List interface extensively, most probably and you decide to jump in with an ArrayDeque. Using it for internal implementations might be a good idea...

ArrayDeque is new with Java 6, which is why a lot of code (especially projects that try to be compatible with earlier Java versions) don't use it.
It's "better" in some cases because you're not allocating a node for each item to insert; instead all elements are stored in a giant array, which is resized if it gets full.

ArrayDeque and LinkedList are implementing Deque interface but implementation is different.
Key differences:
The ArrayDeque class is the resizable array implementation of the Deque interface and LinkedList class is the list implementation
NULL elements can be added to LinkedList but not in ArrayDeque
ArrayDeque is more efficient than the LinkedList for add and remove operation at both ends and LinkedList implementation is efficient for removing the current element during the iteration
The LinkedList implementation consumes more memory than the ArrayDeque
So if you don't have to support NULL elements && looking for less memory && efficiency of add/remove elements at both ends, ArrayDeque is the best
Refer to documentation for more details.

I don't think ArrayDeque is better than LinkedList. They are different.
ArrayDeque is faster than LinkedList on average. But for adding an element, ArrayDeque takes amortized constant time, and LinkedList takes constant time.
For time-sensitive applications that require all operations to take constant time, only LinkedList should be used.
ArrayDeque's implementation uses arrays and requires resizing, and occasionally, when the array is full and needs to add an element, it will take linear time to resize, resulting the add() method taking linear time. That could be a disaster if the application is very time-sensitive.
A more detailed explanation of Java's implementation of the two data structures is available in the "Algorithms, Part I" course on Coursera offered by Princeton University, taught by Wayne and Sedgewick. The course is free to the public.
The details are explained in the video "Resizing Arrays" in the "Stacks and Queues" section of "Week 2".

although ArrayDeque<E> and LinkedList<E> have both implemented Deque<E> Interface, but the ArrayDeque uses basically Object array E[] for keeping the elements inside its Object, so it generally uses index for locating the head and tail elements.
In a word, it just works like Deque (with all Deque's method), however uses array's data structure. As regards which one is better, depends on how and where you use them.

That's not always the case.
For example, in the case below linkedlist has better performance than ArrayDeque according to leetcode 103.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> rs=new ArrayList<>();
if(root==null)
return rs;
// 👇 here ,linkedlist works better
Queue<TreeNode> queue=new LinkedList<>();
queue.add(root);
boolean left2right=true;
while(!queue.isEmpty())
{
int size=queue.size();
LinkedList<Integer> t=new LinkedList<>();
while(size-->0)
{
TreeNode tree=queue.remove();
if(left2right)
t.add(tree.val);
else
t.addFirst(tree.val);
if(tree.left!=null)
{
queue.add(tree.left);
}
if(tree.right!=null)
{
queue.add(tree.right);
}
}
rs.add(t);
left2right=!left2right;
}
return rs;
}
}

Time complexity for ArrayDeque for accessing a element is O(1) and that for LinkList is is O(N) to access last element. ArrayDeque is not thread safe so manually synchronization is necessary so that you can access it through multiple threads and so they they are faster.

Related

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. This list could be as small as 10 objects or as large as a few thousand. I then always want to insert just one object at index 0 of that returned List. 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. 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?
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?
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. 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. (see Why are memcpy() and memmove() faster than pointer increments? ).
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.
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.
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)
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. 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)
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).
If the returned impl is LinkedList, inserting at head is 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. 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.
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.
KISS: Just insert the element into the returned list. I'm sure it will be faster enough, and most likely way faster than the library anyway.

Which implementation to use when creating a List from Iterable

I find myself frequently doing the following:
Iterator<A> itr = iterableOfA.getIterator();
List<B> list = new ArrayList<>(); // how about LinkedList?
while (itr.hasNext()) {
B obj = iter.next().getB();
list.add(obj);
}
someMethod(list); // this method takes an Iterable
I have no idea just how many elements are likely to be in iterableOfA — could be 5, could be 5000. In this case, would LinkedList be a better implementation to use here (since list.add(obj) would then be O(1))? As it stands, if iterableOfA has 5000 elements, this will lead to many resizings of backing array of list.
Other option is to do:
Iterator<A> itr = iterableOfA.getIterator();
int size = Iterables.size(iterableOfA); // from Guava
List<B> list = new ArrayList<>(size);
// and the rest...
This means double iteration of iterableOfA. Which option would be best when the size of the iterable is unknowns and can vary wildly:
Just use ArrayList.
Just use LinkedList.
Count the elements in iterableOfA and allocate an ArrayList.
Edit 1
To clarify some details:
I am optimizing primarily for performance and secondarily for memory usage.
list is a short-lived allocation as at the end of the request no code should be holding a reference to it.
Edit 2
For my specific case, I realized that someMethod(list) doesn't handle an iterable with greater than 200 elements, so I decided to go with new ArrayList<>(200) which works well enough for me.
However, in the general case I would have preferred to implement the solution outlined in the accepted answer (wrap in a custom iterable, obviating the need for allocating a list).
All the other answers gave valuable insight into how suitable ArrayList is compared to LinkedList, so on behalf of the general SO community I thank you all!
Which option would be best when the size of the iterable is unknowns and can vary wildly
It depends what you are optimizing for.
If you are optimizing for performance, then using ArrayList is probably faster. Even though ArrayList will need to resize the backing array, it does this using an exponential growth pattern. However, it depends on the overheads of iteration.
If you are optimizing for long-term memory usage, consider using ArrayList followed by trimToSize().
If you are optimizing for peak memory usage, the "count first" approach is probably the best. (This assumes that you can iterate twice. If the iterator is actually a wrapper for a lazy calculation .... this may be impossible.)
If you are optimizing to reduce GC, then "count first" is probably best, depending on the details of the iteration.
In all cases you would be advised to:
Profile you application before you spend more time on this issue. In a lot of cases you will find that this is simply not worth your effort in optimizing.
Benchmark the two alternatives that you are considering, using the classes and typical data structures from your application.
As it stands, if iterableOfA has 5000 elements, this will lead to many resizings of backing array of list.
The ArrayList class resizes to a new size that proportional to the current size. That means that the number of resizings is O(logN), and the overall cost of N list append calls is O(N).
I would completely skip copying the elements to a new collection.
We have utility code for easily wrapping Iterators into Iterables and Filter for converting between types, but the gist of it is:
final Iterable<A> iofA ... ;
Iterable<B> iofB = new Iterable<B>() {
public Iterator<B> iterator() {
return new Iterator<B>() {
private final Iterator<A> _iter = iofA.iterator();
public boolean hasNext() { return _iter.hasNext(); }
public B next() { return _iter.next().getB(); }
};
}
};
No additional storage, etc. necessary.
3rd option is not bad. For getting size, most of the collections just return the counter that they maintain internally...it does not iterate through the entire list. It depends on the implementation, but all the java.util.xxx collection classes does that way.
If u know what are the potential types of "iterableOfA", u can check how they are doing size.
If "iterableOfA" is going to be some custom implementation and you are not sure how size is done, linkedlist would be safer. That is because ur size varies and potential of resizing is higher, hence u will not get a predictable performance.
Also not sure what operations you are performing in the collection that you are filling "B", your choice would depend on that also.
LinkedList is a cache-hostile memory eating moster, which its father (Joshua Bloch) regrets.
I'd bet, it's not faster in your case as ArrayList resizing is optimized and takes amortized O(1) per element, too.
Basically, the only case when LinkedList is faster, is the following loop:
for (Iterator<E> it = list.iterator(); it.hasNext(); ) {
E e = it.next();
if (someCondition(e)) e.remove();
}
As it stands, if iterableOfA has 5000 elements, this will lead to many resizings of backing array of list.
Many is something like log(5000 / 10) / log(1.5), i.e., 15. But the count doesn't matter much as the last resizings dominate. You'll be copying each object reference maybe twice, that's cheap.
Assuming you'll be doing anything with the list, it's very cheap .
Iterating just to find out the number of elements might help in some cases, but the speed depends on the input Iterable. So unless you need the speed really badly and you know that the input is never really slow, I'd refrain from such an optimization.

java linkedlist slower than arraylist when adding elements?

i thought linkedlists were supposed to be faster than an arraylist when adding elements? i just did a test of how long it takes to add, sort, and search for elements (arraylist vs linkedlist vs hashset). i was just using the java.util classes for arraylist and linkedlist...using both of the add(object) methods available to each class.
arraylist out performed linkedlist in filling the list...and in a linear search of the list.
is this right? did i do something wrong in the implementation maybe?
***************EDIT*****************
i just want to make sure i'm using these things right. here's what i'm doing:
public class LinkedListTest {
private List<String> Names;
public LinkedListTest(){
Names = new LinkedList<String>();
}
Then I just using linkedlist methods ie "Names.add(strings)". And when I tested arraylists, it's nearly identical:
public class ArrayListTest {
private List<String> Names;
public ArrayListTest(){
Names = new ArrayList<String>();
}
Am I doing it right?
Yes, that's right. LinkedList will have to do a memory allocation on each insertion, while ArrayList is permitted to do fewer of them, giving it amortized O(1) insertion. Memory allocation looks cheap, but may be actually be very expensive.
The linear search time is likely slower in LinkedList due to locality of reference: the ArrayList elements are closer together, so there are fewer cache misses.
When you plan to insert only at the end of a List, ArrayList is the implementation of choice.
Remember that:
there's a difference in "raw" performance for a given number of elements, and in how different structures scale;
different structures perform differently at different operations, and that's essentially part of what you need to take into account in choosing which structure to use.
So, for example, a linked list has more to do in adding to the end, because it has an additional object to allocate and initialise per item added, but whatever that "intrinsic" cost per item, both structures will have O(1) performance for adding to the end of the list, i.e. have an effectively "constant" time per addition whatever the size of the list, but that constant will be different between ArrayList vs LinkedList and likely to be greater for the latter.
On the other hand, a linked list has constant time for adding to the beginning of the list, whereas in the case of an ArrayList, the elements must be "shuftied" along, an operation that takes some time proportional to the number of elements. But, for a given list size, say, 100 elements, it may still be quicker to "shufty" 100 elements than it is to allocate and initialise a single placeholder object of the linked list (but by the time you get to, say, a thousand or a million objects or whatever the threshold is, it won't be).
So in your testing, you probably want to consider both the "raw" time of the operations at a given size and how these operations scale as the list size grows.
Why did you think LinkedList would be faster? In the general case, an insert into an array list is simply a case of updating the pointer for a single array cell (with O(1) random access). The LinkedList insert is also random access, but must allocate an "cell" object to hold the entry, and update a pair of pointers, as well as ultimately setting the reference to the object being inserted.
Of course, periodically the ArrayList's backing array may need to be resized (which won't be the case if it was chosen with a large enough initial capacity), but since the array grows exponentially the amortized cost will be low, and is bounded by O(lg n) complexity.
Simply put - inserts into array lists are much simpler and therefore much faster overall.
Linked list may be slower than array list in these cases for a few reasons. If you are inserting into the end of the list, it is likely that the array list has this space already allocated. The underlying array is usually increased in large chunks, because this is a very time-consuming process. So, in most cases, to add an element in the back requires only sticking in a reference, whereas the linked list needs the creation of a node. Adding in the front and the middle should give different performance in for both types of list.
Linear traversal of the list will always be faster in an array based list because it must only traverse the array normally. This requires one dereferencing operation per cell. In the linked list, the nodes of the list must also be dereferenced, taking double the amount of time.
When adding an element to the back of a LinkedList (in Java LinkedList is actually a doubly linked list) it is an O(1) operation as is adding an element to the front of it. Adding an element on the ith position is roughly an O(i) operation.
So, if you were adding to the front of the list, a LinkedList would be significantly faster.
ArrayList is faster in accessing random index data, but slower when inserting elements in the middle of the list, because using linked list you just have to change reference values. But in an array list you have to copy all elements after the inserted index, one index behind.
EDIT: Is not there a linkedlist implementation which keeps the last element in mind? Doing it this way would speed up inserting at the end using linked list.

Which implementation of List to use?

In my program I often use collections to store lists of objects. Currently I use ArrayList to store objects.
My question is: is this a best choice? May be its better to use LinkedList? Or something else?
Criteria to consider are:
Memory usage
Performance
Operations which I need are:
Add element to collection
Iterate through the elements
Any thoughts?
Update: my choice is : ArrayList :) Basing on this discussion as well as the following ones:
When to use LinkedList over ArrayList?
List implementations: does LinkedList really perform so poorly vs. ArrayList and TreeList?
I always default to ArrayList, and would in your case as well, except when
I need thread safety (in which case I start looking at List implementations in java.util.concurrent)
I know I'm going to be doing lots of insertion and manipulation to the List or profiling reveals my usage of an ArrayList to be a problem (very rare)
As to what to pick in that second case, this SO.com thread has some useful insights: List implementations: does LinkedList really perform so poorly vs. ArrayList and TreeList?
I know I'm late but, maybe, this page can help you, not only now, but in the future...
Linked list is faster for adding/removing inside elements (ie not head or tail)
Arraylist is faster for iterating
It's a classic tradeoff between insert vs. retrieve optimization. Common choice for the task as you describe it is the ArrayList.
ArrayList is fine for your (and most other) purposes. It has a very small memory overhead and has good amortized performance for most operations. The cases where it is not ideal are relatively rare:
The list ist very large
You frequently need to do one of these operations:
Add/remove items during iteration
Remove items from the beginning of the list
If you're only adding at the end of the list, ArrayList should be ok. From the documentation of ArrayList:
The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost
and ArrayList should also use less memory than a linked list as you don't need to use space for the links.
It depends on your usage profile.
Do you add to the end of the list? Both are fine for this.
Do you add to the start of the list? LinkedList is better for this.
Do you require random access (will you ever call get(n) on it)? ArrayList is better for this.
Both are good at iterating, both Iterator implementations are O(1) for next().
If in doubt, test your own app with each implementation and make your own choice.
Given your criteria, you should be using the LinkedList.
LinkedList implements the Deque interface which means that it can add to the start or end of the list in constant time (1). In addition, both the ArrayList and LinkedList will iterate in (N) time.
You should NOT use the ArrayList simply because the cost of adding an element when the list is full. In this case, adding the element would be (N) because of the new array being created and copying all elements from one array to the other.
Also, the ArrayList will take up more memory because the size of your backing array might not be completely filled.

Which list<Object> implementation will be the fastest for one pass write, read, then destroy?

What is the fastest list implementation (in java) in a scenario where the list will be created one element at a time then at a later point be read one element at a time? The reads will be done with an iterator and then the list will then be destroyed.
I know that the Big O notation for get is O(1) and add is O(1) for an ArrayList, while LinkedList is O(n) for get and O(1) for add. Does the iterator behave with the same Big O notation?
It depends largely on whether you know the maximum size of each list up front.
If you do, use ArrayList; it will certainly be faster.
Otherwise, you'll probably have to profile. While access to the ArrayList is O(1), creating it is not as simple, because of dynamic resizing.
Another point to consider is that the space-time trade-off is not clear cut. Each Java object has quite a bit of overhead. While an ArrayList may waste some space on surplus slots, each slot is only 4 bytes (or 8 on a 64-bit JVM). Each element of a LinkedList is probably about 50 bytes (perhaps 100 in a 64-bit JVM). So you have to have quite a few wasted slots in an ArrayList before a LinkedList actually wins its presumed space advantage. Locality of reference is also a factor, and ArrayList is preferable there too.
In practice, I almost always use ArrayList.
First Thoughts:
Refactor your code to not need the list.
Simplify the data down to a scalar data type, then use: int[]
Or even just use an array of whatever object you have: Object[] - John Gardner
Initialize the list to the full size: new ArrayList(123);
Of course, as everyone else is mentioning, do performance testing, prove your new solution is an improvement.
Iterating through a linked list is O(1) per element.
The Big O runtime for each option is the same. Probably the ArrayList will be faster because of better memory locality, but you'd have to measure it to know for sure. Pick whatever makes the code clearest.
Note that iterating through an instance of LinkedList can be O(n^2) if done naively. Specifically:
List<Object> list = new LinkedList<Object>();
for (int i = 0; i < list.size(); i++) {
list.get(i);
}
This is absolutely horrible in terms of efficiency due to the fact that the list must be traversed up to i twice for each iteration. If you do use LinkedList, be sure to use either an Iterator or Java 5's enhanced for-loop:
for (Object o : list) {
// ...
}
The above code is O(n), since the list is traversed statefully in-place.
To avoid all of the above hassle, just use ArrayList. It's not always the best choice (particularly for space efficiency), but it's usually a safe bet.
There is a new List implementation called GlueList which is faster than all classic List implementations.
Disclaimer: I am the author of this library
You almost certainly want an ArrayList. Both adding and reading are "amortized constant time" (i.e. O(1)) as specified in the documentation (note that this is true even if the list has to increase it's size - it's designed like that see http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html ). If you know roughly the number of objects you will be storing then even the ArrayList size increase is eliminated.
Adding to the end of a linked list is O(1), but the constant multiplier is larger than ArrayList (since you are usually creating a node object every time). Reading is virtually identical to the ArrayList if you are using an iterator.
It's a good rule to always use the simplest structure you can, unless there is a good reason not to. Here there is no such reason.
The exact quote from the documentation for ArrayList is: "The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation."
I suggest benchmarking it. It's one thing reading the API, but until you try it for yourself, it'd academic.
Should be fair easy to test, just make sure you do meaningful operations, or hotspot will out-smart you and optimise it all to a NO-OP :)
I have actually begun to think that any use of data structures with non-deterministic behavior, such as ArrayList or HashMap, should be avoided, so I would say only use ArrayList if you can bound its size; any unbounded list use LinkedList. That is because I mainly code systems with near real time requirements though.
The main problem is that any memory allocation (which could happen randomly with any add operation) could also cause a garbage collection, and any garbage collection can cause you to miss a target. The larger the allocation, the more likely this is to occur, and this is also compounded if you are using CMS collector. CMS is non-compacting, so finding space for a new linked list node is generally going to be easier than finding space for a new 10,000 element array.
The more rigorous your approach to coding, the closer you can come to real time with a stock JVM. But choosing only data structures with deterministic behavior is one of the first steps you would have to take.

Categories

Resources