According to this posting, it is said that ListBuffer allows constant-time removal of the first and last elements. I've been looking into the API reference and the ListBuffer source code, but I can't find how I remove the last element in constant time while remove(0) will do the job for the first element. What would be the proper way to remove the last element?
Another question: is it possible to remove an element efficiently while iterating over a ListBuffer? In Java it can be done with Iterator.remove() but the Scala iterator doesn't seem to have the remove() method...
The first question has an easy if disappointing answer: you can't remove the last element in constant time, as doing so would require a reference to the element-before-last. (It's a singly linked list, inside a wrapper class that holds the beginning and end elements of the list.)
The second question is equally easy and perhaps disappointing: Iterators in Scala are simply views of the collection. They don't modify the underlying collection. (This is in keeping with the "immutable by default, mutable only when necessary" philosophy.)
You can remove the last element with trimEnd(1)
Related
My main question is if ListIterator or Iterator class reduces the time taken for removal of the elements from a given LinkedList and the same can be said while adding elements in the same given LinkedList using any one of the following classes above. What's the point of using the inbuilt functions of LinkedList class itself? Why should we perform any of the operations through LinkedList functions when we can use the ListIterator functions for better performance?
A ListIterator can indeed efficiently remove the node on which it is positioned. You can thus create a ListIterator, use next() two times to move the cursor, and then remove the node instantly. But evidently you did a lot of work before the actual removal.
Using ListIterator.remove is not more efficient "time complexity"-wise than removing through the LinkedList.remove(int index) if you need to construct the iterator. The LinkedList.remove method takes O(k) time, with k the index of the item you wish to remove. Removing this element with the ListIterator has the same timecomplexity since: (a) we create a ListIterator in constant time; (b) we call .next() k times, each operation in O(1); and (c) we call .remove() which is again O(1). But since we call .next() k times, this is thus an O(k) operation as well.
A similar situation happens for .add(..) on an arbitrary location (an "insert"), except that we here of course insert a node, not remove one.
Now since the two have the same time complexity, one might wonder why a LinkedList has such remove(int index) objects in the first place. The main reason is programmer's convenience. It is more convenient to call mylist.remove(5), than to create an iterator, use a loop to move five places, and then call remove. Furthermore the methods on a linked list guard against some edge-cases like a negative index, etc. By doing this manually you might end removing the first element, which might not be the intended behaviour. Finally code written is sometimes read multiple times. If a future reader reads mylist.remove(5), they understand that it removes the fifth element, wheres a solution with looping will require some extra brain cycles to understand what that part is doing.
As #Andreas says, furthermore the List interface defines these methods, and hence the LinkedList<T> should implement these.
I know there are a lot of similar questions here on SO. But it seems this wasn't discussed before.
In general I want to know, why an Iterator should be used over a For-Each loop, if no element will be removed? So, basically just iterating over a Collection, and the only used modifier is add.
I'm aware that Iterator is the only save option if an element is removed from a Collection.
Performance is no argument, because the For-Each will be transformed into an Iterator by the compiler.
The Iterator is more verbose, so +1 to For-Each.
Is there any reliable point to use an Iterator over For-Each in the described scenario?
You need to use an Iterator loop instead of a foreach loop if
you need to be able to remove items during processing, OR
you need to process the last item differently than the others.
Also, an Iterator may be more natural if you want to be able to skip an element based on characteristics of its previous element.
Additionally, for Lists, a ListIterator loop may sometimes be more convenient than a foreach loop, as it can provide the indexes of the previous and next elements, and (even apart from the indexes) allows you to recognize the first element of the iteration. Furthermore, you need a ListIterator if
you have to replace elements in the underlying List, OR
you ever need to back up.
Main Question:
I'm seeking some way to give an object within a LinkedList a reference to itself within the list so that it can (efficiently) remove itself from said list (Without sorting through the list looking for itself. I'd like it to just directly cut itself from the list and tie the previous and next items together.).
Less Necessary Details:
I've done a reasonable amount of googling and not found anything other than people advising not to use circular references.
I'd like to do this as I'm designing a game, and in the game objects can implement various interfaces which allow them to be in various lists which are looped through in a prioritized manner. A single object might be in a draw loop, a loop which steps it through the frames of its animation, a high priority logic loop, and a low priority logic loop all at the same time. I would like to implement a removeFrom|TypeOfLoop| method in each appropriate interface so that if an object decides that it no longer needs to be in a loop it can directly remove itself. This keeps the objects that do the actual looping pleasantly simple.
Alternatively, If there is no way to do this, I'm thinking of implementing a flagging system where the list checks to see if each item wants to be removed based on a variable within the item. However, I dislike the idea of doing this enough to possibly just make my own LinkedList that is capable of removing by reference.
I did this recently. I was looking for an O(1) add O(1) remove lock-free Collection. Eventually I wrote my own Ring because I wanted a fixed-size container but you may find the technique I used for my first attempt of value.
I don't have the code in front of me but if memory serves:
Take a copy of Doug Lea's excellent Concurrent Doubly LinkedList and:
Expose the Node class. I used an interface but that is up to you.
Change the add, offer ... methods to return a Node instead of boolean. It is now no longer a java Collection, but see my comment later.
Expose the delete method of the Node class or add a remove method that takes a Node.
You can now remove elements from the list in O(1) time, and it is Lock Free.
Added
Here's an implementation of the remove(Node) method taken from his Iterator implementation. Note that you have to keep trying until you succeed.
public void remove(Node<E> n) {
while (!n.delete() && !n.isDeleted())
;
}
I think your alternative is much better than letting the item remove itself from the loop. It reduces the responsibilities of the objects in the list, and avoids circular references.
Moreover, You could use Guava's Iterables.filter() method and iterate over a filtered list, rather than checking explicitely if the object should be rendered or not at each iteration.
Even if what you want to do was possible, you would get a ConcurrentModificationException when removing an object from the list while iterating on it. The only way to do that is to remove the current object from the iterator.
If you're using LinkedList, there's no more efficient way to remove an item than to iterate over it and do iterator.remove() when you find your element.
If you're using google collections or guava, you can do it in a oneliner:
Iterables.removeIf(list.iterator(), Predicates.equalTo(this));
The easiest way would be changing your algorithm to use Iterator to iterate over List objects and use Iterator.remove() method to remove current element.
I have a PriorityQueue that has an element with a priority. Now I want to add the same element again with a different priority and keep only the one with higher priority. I thought of checking the new element against the already present one and then deciding whether to keep the old one or replace, but I can't find a way to compare my new element against an arbitrary element from the PriorityQueue.
a PriorityQueue was not meant to access an arbitrary element in it, it is designed to allow fast access to the head alone. If you need to do this operation frequently, probably a java.util.TreeSet will be a better data structure.
However, you can access any element by iterating PriorityQueue [using an Iterator] and breaking when you find your match. You cannot get performance better then O(n) for getting an arbitrary element in any case for a PriorityQueue, because it was not designed to do it.
I was reading a thread here about the performance of java ArrayList and LinkedList. There is an answer from Mr Kevin Brock that reads the following.
"Linked list add is not always O(1)
[or this should say addLast() is
O(1)]. This is only true if done from
within a ListIterator. The add methods
in Java's LinkList implementation must
search through the list if additions
are not on the head or tail."
I din't understand what he meant by "only if done through ListIterator". Does it mean there is a data structure within the linkedlist that holds the reference of each index and as soon as we get the listiterator from a certain index, listiterator is returned straight away without walking through the list to find that index?
Thanks guys!
It means that iterator points to list nodes directly; and so access via get(int) will be O(N), but iterator.next() wil be O(1). Latter has direct reference and does not need to traverse anything; former will need to traverse from head of the list.
If you add to a LinkedList where the ListIterator is pointing to, it is O(1). This is the same as adding to the start of the LinkedList or the end of an ArrayList.
The comment refers to the two argument add method, [add(int,E)][1]. Assuming a linearly distributed index, then this will be O(n) as the list needs to be iterated through to find the appropriate node. It does not apply to add(E).
[1]: http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html#add(int, E)