In the Collection framework tutorials for the List interface, there is an interesting quote regarding performance of removal of elements from a List implementation:
For many common List implementations, such as ArrayList, the performance of removing elements from the end of the list is substantially better than that of removing elements from the beginning.
The tutorials do not go further into explaining this and I am trying to understand exactly why it might be so.
Considering an ArrayList<Integer> list as below:
In the first scenario, if we remove the last 4 elements from the end of the list, then the values of these are set to null (or equivalent). My theory is that, when a copy operation is necessary, only the elements that are not null will be copied.
In the second scenario, if we remove the first 4 elements, they would be set to null again and again only non-null elements would be copied.
So from this point of view, the performances appear to be around the same. Is there another reason why the operation is faster if performed from the end?
On the other hand, for LinkedList, the inverse appears to be true; removal from the beginning is faster, whereas removal from the end requires an almost full traversal unless a tail-pointer
is kept.
As per my understanding,
ArrayList is an array implementation of a list. So if you remove elements from the beginning of an array you need to move all the remaining elements to fill up the elements that you removed. So this is going to essentially be a O(n-1) operation.However this is not the case when you remove elements from end of the list. This will be O(1).
There is more to removing elements from the beginning of the list than just setting the elements to null. You also need to move the remaining elements to fill in the vacated locations.
It's possible to use a variable to keep track of the "beginning" of the list without moving elements, but then you will sacrifice memory efficiency because of the unused elements in the array.
In ArrayList<> removing from start is slow because entire array will have to be shifted since the add function add the elements at and if we left the start empty then we will be wasting the memory.
If we take into account big(O) notation removing from start is essentially linear time O(n) while deleting from end is constant time O(1).
While Code-Apprentice's answer is correct, I'd like to elaborate on how you can verify the behavior that every entry is moved to the left by making an index-based lookup, i.e., calling list.get(index).
add two entries
remove the first element
check the value of the first element: is it now null or the previously second element?
The code to verify:
List<String> list = new ArrayList<>();
list.add("0");
list.add("1");
list.remove(0);
String entry0 = list.get(0);
System.out.println(entry0);
You suspected that null would be printed, but "1" is printed.
This confirms that all the elements are shifted to the left.
NB. I used Strings to avoid the confusion caused by remove(int index) and remove(Object o).
Related
I have found following question on www.javatpoint.com
If you were to use a List implementation,but not sure which one to, because the requirement is not yet clear. In this case which List implementation will you use ?
options:
1. ArrayList
2. LinkedList
Correct answer for this is ArrayList
But there is no explanation why, Please help me to uderstand
Simple Term
ArrayList : Iterating Over An ArrayList is faster than Linked List, Because All Elements Stored in Contiguous Memory Location. But Performing Operation Like Delete Will Reduce Performance Because Again Entire List Order Changes (Like if you delete element at position 3rd then all next elements location are currentLocation - 1).
LinkedList : Slower When Iteration Performed(As Compare To ArrayList). But Delete and Update Operation Becomes Faster Because If you delete any element at any position only previous and after element locations are changed(Not Entire List).
So When You Don't Have Clear Requirements Just Iteration Is Basic Need (And Array List Gives Best Performance).
One possible reason might be that elements in ArrayList consume less memory space than in LinkedList, because each element in LinkedList contains a value plus a pointer to the next element, while an element in ArrayList has only value
ArrayList stores elements in array in insert order. You can get value by its index in array.
LinkedList stores your elements in Node objects that references each other. Each Node references previous and next Node. You can get elements sequentially starting from both sides. You can also get elements by index but it's not as fast as in ArrayList. Use LinkedList when you need sequential access, like queue or stack data structure
From what I've read in the past: An ArrayList essentially acts as a better array, allowing for dynamic resizing. A LinkedList is a double linked list which causes it to have better performance on adding and removing items from the list, but getting and setting at arbitrary positions is slower than an ArrayList. So, the question is most likely assuming that, generally, a program will be getting and setting values more than it is adding and removing values, which is a fairly reasonable assumption, but the question in question is incorrect.
I think I am missing a very obvious point but could not find it in my Java textbook.
I understand that node storage does not necessarily have to be contiguous in memory for linked list. Does this also mean that a linked list is not indexable? If so, then the only way to find an item in a linked list is to traverse the list, right, whereas you can get from an array by index?
Why is accessing an item by index slower in a linked list than an array?
A linked list has a chain of entries. If you want to get (say) the element at position 42, the code has to:
get the entry for the first element (position 0)
follow the next link to the entry for position 1
follow the next link to the entry for position 2
and so on .... 42 times in total.
There is no short cut.
I am still not understanding why a linked list is not indexable ....
Now a LinkedList is indexable in the sense that there is a get(int) operation that works. It is just that indexing a LinkedList is inefficient. In general, it takes O(N) steps to perform a get(i) in a linked list of length N. By contrast with an array, or an ArrayList, you can retrieve any element of the data structure in one step. We say that the complexity is O(1).
Contrast this with Set objects in general, and HashSet in particular. The HashSet class is NOT indexable because there is no get(int) method to retrieve the set element at position i. Indeed, even the notion of "position i" in a set is meaningless. The ordering of the elements in a Set is unspecified and (for some Set implementations, like HashSet) it may be effectively indeterminate.
Some Linked list implementations provide a way to access to it's elements using index, but the fact is that if you want to get 10th element in linked list your compiler still has to go through all the sequence from 0 to 9 because the elements may be spread over the memory. On the other hand when you ask for 10th element in an array using index, compiler computes the exact position of 10th element and jumps directly to that element. Array and list have different purposes; if your algorithm requires go back and forward over your data structure, then it is much efficient to use array. If you need mostly add/remove operations, then it is efficient to use list
With a linked list you can add and remove elements at any time so index it has no sense. Imagine that you create an index that points at the third element of the list. After that, you insert a new element at the beginning of the list. What value should return the index?
However it could be possible for example create an index at the middle of the list and use it only if you add o remove elements in the last half of the list.
#paxdiablo explains it very well here Is there a known implementation of an indexed linked list?
I think it is a standard problem. I need a list that I can iterate for and backward. If iterating forward and the iterator riches e.g. 80% of length of the list, new element must be added to the end of list and the same number of elements must be deleted from the beginning of list. This should happen during iteration without influencing the iterator. The current iterator should be still valid. The same procedures should work, if the iterator goes backward.
Is there any kind of list, queue or stack in any collection that fulfills these requirements? Anybody know?
Thx
this can be very easily implemented using array.
Set initial size of the array.
Create Array of that size and you desired type
Create index (int for example) which is incremented/decreased when iterating the array.
Add logic to track the index (e.g. if index>0.8*size -> add more elements to the array)
I would use the java ArrayList object for this job.
What you are talking about is not an endless list, but a circular list (endless list would not delete from the beginning).
What you want is a function with a normal list inside, that takes an iterator as parameter and just rolls over when it reaches the end. So element 101 of 100 element list, is element 1 being overwritten.
I am working on an algorithm that will store a small list of objects as a sublist of a larger set of objects. the objects are inherently ordered, so an ordered list is required.
The most common operations performed will be, in order of frequency:
retrieving the nth element from the list (for some arbitrary n)
inserting a single to the beginning or end of the list
removing the first or last n elements from the list (for some
arbitrary n)
removing and inserting from the middle will never be done so there is no need to consider the efficiency of that.
My question is what implementation of List is most efficient for this use case in Java (i.e. LinkedList, ArrayList, Vector, etc)? Please defend your answer by explaining the implementation s of the different data structures so that I can make an informed decision.
Thanks.
NOTE
No, this is not a homework question. No, I do not have an army research assistants who can do the work for me.
Based on your first criteria (arbitrary access) you should use an ArrayList. ArrayLists (and arrays in general) provide lookup/retrieval in constant time. In contrast, it takes linear time to look up items in a LinkedList.
For ArrayLists, insertion or deletion at the end is free. It may also be with LinkedLists, but that would be an implementation-specific optimization (it's linear otherwise).
For ArrayLists, insertion or deletion at front requires linear time (with consistent reuse of space, these may become constant depending on implementation). LinkedList operations at front of list are constant.
The last two usage cases somewhat balance each other out, however your most common case definitely suggests array-based storage.
As far as basic implementation details:
ArrayLists are basically just sequential sections of memory. If you know where the beginning is, you can just do a single addition to find the location of any element. Operations at the front are expensive because elements may have to be shifted to make room.
LinkedLists are disjoint in memory and consist of nodes linked to each other (with a reference to the first node). To find the nth node, you have to start at the first node and follow links until you reach the desired node. Operations at the front just require creating a node and updating your start pointer.
I vote for double linked list. http://docs.oracle.com/javase/6/docs/api/java/util/Deque.html
Probably the best data structure for this purpose would be a deque implemented with a dynamic array, which is basically an ArrayList that starts adding elements to the middle of the internal array instead of the beginning. Unfortunately Java's ArrayDeque does not support looking up an nth element.
It is, however, pretty easy to implement one yourself (or lookup an existing implementation), and then all three of the described operations can be done in O(1).
YOu can do all of them with arrayList with minimal confusion if your not worried about efficiency.
i would uses some sort of a queue or stack if i am only inserting at the front or end. They have the least overhead. Or you could also use a linked list.
To remove N elements from the first or end i would use a linked list, you can just delete one node and the ones before or after it are gone. Ie if i delete the first 5 elements just delete the 5th element and the ones before it will disappear. Also if i delete the last 6 elements just delete the 6th to last one and the rest will disappear. And java will do the garbage collecting for you. This would be an order of (1) for this operation.
is this a homework question?
Definitely go for LinkedList. For both inserting a value at the beginning/end of the list and removing the first/last element in the list, it runs in O(1). This is because all that needs to be changed to carry out these operations is a couple of pointers, a minimally costly operation.
Although ArrayLists retrieve the nth element in O(1) while LinkedLists retrieve the nth element in O(n), ArrayLists run the danger of having to adjust their size when elements are inserted. What do you suppose happens when the memory allotted for the ArrayList is used up and you try to insert another element? Well what happens is the ArrayList duplicates itself then allocates more memory (amounting to twice as much as it had initially allocated), a very costly operation. LinkedLists don't have this problem since, again, all that is done is the addition of a pointer.
I don't know a whole lot about Java Vectors, but if they're anything like C++ vectors, then they're very similar to ArrayLists.
I hope this helps.
java.util.TreeMap of Long to Object, and use index of i+tm.firstKey()
I have string array (String[]) and I need to remove the first item. How can I do that efficiently?
The size of arrays in Java cannot be changed. So, technically you cannot remove any elements from the array.
One way to simulate removing an element from the array is to create a new, smaller array, and then copy all of the elements from the original array into the new, smaller array.
String[] yourArray = Arrays.copyOfRange(oldArr, 1, oldArr.length);
However, I would not suggest the above method. You should really be using a List<String>. Lists allow you to add and remove items from any index. That would look similar to the following:
List<String> list = new ArrayList<String>(); // or LinkedList<String>();
list.add("Stuff");
// add lots of stuff
list.remove(0); // removes the first item
Simplest way is probably as follows - you basically need to construct a new array that is one element smaller, then copy the elements you want to keep to the right positions.
int n=oldArray.length-1;
String[] newArray=new String[n];
System.arraycopy(oldArray,1,newArray,0,n);
Note that if you find yourself doing this kind of operation frequently, it could be a sign that you should actually be using a different kind of data structure, e.g. a linked list. Constructing a new array every time is an O(n) operation, which could get expensive if your array is large. A linked list would give you O(1) removal of the first element.
An alternative idea is not to remove the first item at all, but just increment an integer that points to the first index that is in use. Users of the array will need to take this offset into account, but this can be an efficient approach. The Java String class actually uses this method internally when creating substrings.
You can't do it at all, let alone quickly. Arrays in Java are fixed size. Two things you could do are:
Shift every element up one, then set the last element to null.
Create a new array, then copy it.
You can use System.arraycopy for either of these. Both of these are O(n), since they copy all but 1 element.
If you will be removing the first element often, consider using LinkedList instead. You can use LinkedList.remove, which is from the Queue interface, for convenience. With LinkedList, removing the first element is O(1). In fact, removing any element is O(1) once you have a ListIterator to that position. However, accessing an arbitrary element by index is O(n).
Keep an index of the first "live" element of the array. Removing (pretending to remove) the first element then becomes an O(1) time complexity operation.
To sum up, the quick linkedlist method:
List<String> llist = new LinkedList<String>(Arrays.asList(oldArray));
llist.remove(0);
An alternative ugly method:
String[] a ={"BLAH00001","DIK-11","DIK-2","MAN5"};
String[] k=Arrays.toString(a).split(", ",2)[1].split("]")[0].split(", ");