Do we need the previous element in a linked list? - java

In the implementation of HashMap, linked lists are used to represent elements in buckets.
Each Entry has a element to the next Entry. See: Ref. However, in the implementation for the LinkedList class, each element has a reference to its previous element and its next element see Ref. Just trying to figure out why previous is important in one linked list and not another?

Entry (internal class of HashMap) is not a part of general-use linked list (as LinkedList is). It's sole purpose is to iterate over it in forward direction looking for an element. So it does not need a previous reference.

the previous reference make the LinkedList a bidirectional List,this makes it possible to reversely iterate on a List .

The reference to the previous element is not needed in a linked list, stricly speaking. The java.util.LinkedList is actually a doubly-linked list. This is needed for an efficient implementation of the following operations:
add(E), which append at the end of the list;
getLast(), which retrieves the last element of the list;
ListIterator.previous() which allow traversal of the list in reverse order.
Said operations are of no use for the linked list of Map.Entry.
Note that while getLast() is a LinkedList adition to the list interface, the two other are required by the said interface.

The LinkedList is a general-purpose implementation. You may want to iterate over it backwards. For Maps, when searching a bucket it only iterates forward. Since there is not need to iterate backward, it is not implemented.

Related

What LinkedLists in Collection interface are single or doubly?

I very well understand the concept of SLL or DLL.
But which one of them are we using in Collection interface?
So far I have encountered LinkedList in interfaces List,Queue and Dequeue.
Is there any other? And what type of LinkedList are we using in these 3 interfaces?
How can I even know it?
List, Queue and Dequeue are just interfaces which provide a contract to be satisfied by the implementation. It doesn't matter how the list is implemented (in fact it doesn't even have to be a list).
The first line of LinkedList javadoc states
Doubly-linked list implementation of the List and Deque interfaces.
All linked lists in java are doubly linked lists
Arrays and array lists have a major disadvantage: Deleting an element from the middle of the array costs too much. Because all elements in the array after the deleted element must be moved to the front of the array. (The same goes for inserting an element into the array)
And then Java deliver the solution:
Java introduced a linked list to solve the problem. In the Java programming language, all linked lists are actually two-way linked, in which each node also stores a reference to the predecessor node.

Get reference to the most recently added node in a java LinkedList

My aim is to delete a node somewhere in the middle of a Java LinkedList object, in O(1) time.
If I can get a reference to the node, I could probably do this myself without the need for a Java-provided method. But I cannot seem to find a way to get a reference to anything but the head of the list.
How can I get a reference to the last node in a Java LinkedList object? I wold then store these references in a map to use later.
Note: I know this is doable if I implement my own LinkedList, but is there a way to do it with Java's LinkedList class?
I would suggest actually changing your data structure to LinkedHashSet here instead of LinkedList. The reason for this is that LinkedHashSet#get() and remove() can lookup or delete any element by key in O(1) time. Also, a LinkedHashSet is implemented with a linked list running through the entries. The order of the entries while iterating the list are determined by the insertion order, so it behaves similarly to a LinkedList in that regard.
The closest thing you can get to a direct reference is an Iterator that points to a specific point.
If you call remove() on such an Iterator it should work in O(1):
LinkedList<Object> linkedList = ...;
Iterator<Object> it = linkedList.iterator();
while (it.hasNext()) {
if (matchesSomeCondition(it.next()) {
it.remove();
}
}
Note that this sample code definitely doesn't run in O(1), it's specifically just the remove() call that can have that efficiency. If you haven't already identified the node in some way (such as positioning an Iterator at that place), then you won't be able to remove an element from a LinkedList in O(1) time.
Edit and since you mention "last recently added" element then maybe a ListIterator is the thing to use, since it has an add() method. If you can efficiently implement all your adding/removing using a ListIterator, then you can keep the traversal operations over the LinkedList to a minimum. In fact, if you always use indexes to add/remove objects from your LinkedList then you loose a lot of its efficiency (since each add/remove call has to find the affected item first via traversal).

LRU Cache Evict method implementation

If we are implementing a LRU cache using HashMap and DoublyLinkedList, What is the best way to implement evict() method with O(1) time complexity?
LinkedList from Java didn't expose the Node type (which is a private static inner class).
So you can't remove it in in O(1), because a sequential scan is required.
To get O(1), you need to be able to access the Node type, so that could remove it without scan.
You have to write it by yourself. Fortunately, a doubly linked list is relatively easy to write, and it's a pretty beneficial & fun task to do.
How to remove with a given Node?
Refer to this answer: https://stackoverflow.com/a/54593530
The method LinkedList.java -> removeNode() remove a given node, without sequential scan.
The code in this answer is for a singly linked list, the remove for a doubly linked list is even simpler in some case.
Tips:
If the given node is the end node in linked list, then you need the previous node too.
But that's for singly linked list, for a doubly linked node, the node itself contains the previous node, so you don't have to pass previous node to the removeNode() method.
BTW
Why it's beneficial?
linked list is the most basic structure (except array and bits), that some other very basic structures could built base on.
e.g both queue and stack could be implemented easily with a linked list.
Concurrent access
java.util.LinkedList is not thread-safe, your LRU might needs some concurrent control, but I'm not sure.
If need, then java.util.concurrent.ConcurrentLinkedDeque is a good example to refer to.
#Update LinkedHashMap
java.util.LinkedHashMap, is a combination of hashtable & doubly linked list.
Mechanism:
It extends HashMap to get the O(1) complexity for the common operations.
And use doubly linked list to keep track of insertion order.
head is the eldest item, and tail is the newest item.
It can be used to impl some kind of cache, though I am not sure will it be fully qualified for your requirement.

Traversing which object type is the fastest in java

I was wondering which Java collection types are traversed fastest. Collections I am most interested in are...
array
LinkedList
Queue
PriorityLinkedList
HashMap
Actually among concrete classes of Collection interface , traversing will be fast through array. Its because as you know it traverse with the index of the element.Since it follows the index pattern so,traversing through index it makes our traversing fast. Why not others? Let me explain one by one..
1.LinkedList : LinkedList follows the insertion order.If you traverse the data and searching for elements,for every element it will search from beginning. So traversing becomes slow.
2.Queue : LinkedList and PriorityQueue are two concrete classes of Queue. The elements of the priority queue are ordered according to their natural ordering, or by a Comparator provided at queue construction time, depending on which constructor is used.It's not guaranteed to traverse the elements of the priority queue in any particular order.If you need ordered traversal, consider using Arrays.sort(pq.toArray()). So it becomes useless for traversing provided if you traverse without sorting it explicitly.
3.HashMap: If you use Map instead of Collection , traversing is not guaranteed here because it works on hashcode of the key element. So here again traversing becomes useless. You can directly search the element by providing key-value of the element.
4.PriorityLinkedList: This class does not exist in Java APIs.

Java ListIterator Performance

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)

Categories

Resources