1

I am using Java's Linkedlist in my project. I have to build a delete function that removes an element with a specified unique id (id is a filed in my class) in the Linkedlist. As per the Java official document, were I to use LinkedList.remove, the runtime would be O(n) as the process happens in two steps, the first of which is a linear search with a runtime of O(n) followed by the actual delete which takes O(1).

In an attempt to speed things up, I wanted to use a binary tree for lookup, where each node in the tree is (id, reference to the node in the linkedlist). I am not exactly sure how to implement this in Java. In C/C++, one could just store a pointer as reference to the node in the linkedlist.

==

If you are wondering why I have to use LinkedList, it's because I am building an order-matching engine for exchanges. LinkedList offers superior runtime as far as insert is concerned. I am also using insertion sort to keep prices in the orderbook sorted. Priority queue does not suit my needs because I have to show the sorted order book in real time.

The Yellow
  • 47
  • 8
  • 1
    Data structures are all about tradeoffs. If you want better `remove` performance, you may have to forfeit some `insert` performance. You can't have the best of everything, sadly. – Silvio Mayolo Jan 16 '18 at 17:50
  • @SilvioMayolo with my proposed plan, `insert`, with the position known, could be `O(1)` and `delete` with the id known would be `O(logn)`. – The Yellow Jan 16 '18 at 17:53
  • All the really good use cases for linked lists involve external pointers to list nodes... but Java doesn't let you do this, which renders the java LinkedList mostly useless. – Matt Timmermans Jan 16 '18 at 18:13

4 Answers4

3

Have you seen the video of Stroustrup's conference talk where he showed that you should use std::vector unless you have measured a performance benefit of not using std::vector? He showed that std::vector is almost always the correct collection to use, and showed that it is faster than linked list even when inserting and deleting in the middle.

Now translate that to Java: use ArrayList unless you have measured better performance with something else.

Why is that? With modern processor architectures, there is a locality benefit: elements that you compare together, elements that you process together, are all stored next to each other in memory and are likely to be in the CPU's cache at the same time. This allows them to be fetched and written to much faster than when they're in main memory. This is not the case with a linked list, where elements are allocated individually and spread all over the place. (This locality benefit is much more pronounced in C++ where you have the actual objects next to each other, but it's still valid to a smaller extent in Java, where you have the references next to each other, albeit not the actual objects.)

Now with ArrayList, you can keep the orders sorted by price, and use binary search to insert an order in the right place.

If your performance measurement shows that LinkedList is preferable, then unfortunately Java doesn't give you access to the internal representation – the actual nodes – of the LinkedList, so you'll have to homebrew your own list.

Klitos Kyriacou
  • 10,634
  • 2
  • 38
  • 70
  • 1
    In this case, since the OP indicates that things are usually added close to the front, it might be better to use an ArrayList in reverse order – Matt Timmermans Jan 16 '18 at 20:48
2

Why are you using a List?

If you have a unique id for each object, why not put it in a Map with the id as the key? If you choose a HashMap is implementation removal is O(1). If you implement using LinkedHashMap you can preserve insertion order as well.

LinkedList insertion is superior to....what?

HashMap get/put complexity

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • added explanation – The Yellow Jan 16 '18 at 17:47
  • 1
    it is not just the insertion order, I have to add new elements to the correct position when they come in so that the list remains sorted. For example, after adding 5 to [1,2, 4, 6, 8] the linkedlist would become [1,2, 4, 5, 6, 8] – The Yellow Jan 16 '18 at 17:50
  • I don't think you can have both with library collections. It's easy to sort once you've inserted using a Comparable implementation of your choosing. Is order determined by id, creation timestamp, or some other state variable? – duffymo Jan 16 '18 at 18:06
0

To preserve order by id and to get good performance use TreeMap. Put, remove and get operations will be O(log n).

EDIT:

For preserving order of insertion of elements for each id you can use TreeMap < Integer, ArrayList < T > >, i.e. for each id you can save elements with particular id in list in order of insertion.

Anton Tupy
  • 951
  • 5
  • 16
  • the tricky part is that most orders will only go to the front of the order book. say i have an ordebook of [1,2,5,6,7,8,.......(1k elements)], the newly inserted element will mostly likely be within the range of 0 to 5. Insertion sort in this case is better – The Yellow Jan 16 '18 at 18:12
  • You can use TreeMap>, i.e. for each id you can save elements with this id in order of insertion. – Anton Tupy Jan 17 '18 at 05:32
0

You can easily solve this by having a small change. First have an object that has your value and id as fields

class MyElement implements Comparable{
   int id,value;

   //Implement compareTo() to sort based on values

   //Override equals() method to compare ids

   //Override hashcode() to return the id
 }

Now use a TreeSet to store these objects.

In this data structure the incoming objects get sorted and deletion and insertion also find lower time complexity of O(log n)