I'm implementing a sliding window over a stream of events, in Java.
So I want a data structure which allows me to do the following:
add to the end of the data structure when new events occur;
remove from the start of the data structure when old events are processed;
get standard random access (size(), get(i)) to the elements of the data structure; in general, typical List "read" operations;
is efficient for all of the above operations;
is unbounded.
No other access is required. And no thread safety is required.
I'm currently doing this with an ArrayList, to get things up and running. But I want something more efficient; the remove(0) method (2. above) is inefficient with an ArrayList.
Numbers 1. and 2. are standard Queue-style operations. However, the implementations of Queue in the JDK (such as ArrayDeque) don't allow for get(i) in 3.
So, I'm wondering if there are any libraries out there which have such an implementation, and are suitable for commercial use.
If not, I guess I'll resort to writing my own...
Seems like a task for a Circular Buffer - as long as it's okay if the queue has a fixed capacity. I don't know of any standard implementation though. But here is a nice recipe to roll your own.
I got this problem and tried solving it by copying the source code of ArrayDeque and adding something like:
E get(index){ return elements[(head + index) % size];}
If you have a large enough array you can implement a queue with a basic array, and just use an index as to the head of the list, and use the mod operator so you can wrap around if needed.
So, you basically have a circular array that supports the insert and remove functions.
UPDATE:
It is a quick operation to copy an array to a larger array, so just double in size, perhaps, when getting close to the end, and just copy the array, as a step in doing insert. Overall you will still have very fast access, as the norm should not be to increase and copy.
How fast are the events coming in and out of this queue?
On the one hand, you can have a "sufficiently large" circular buffer.
While it is technically "bounded", you can make it "unbounded" by growing it as necessary.
By the same token, you can "shrink" it down in terms of overall capacity when it's "quiet".
But, for many applications a 100, 1000, or even 10000 item capacity circular buffer is effectively unbounded.
The only library I can think of that would implement such an interface would be a LinkedList but frankly I'm not sure what the performance characteristics are.
Just throwing this out there as an alternative to rolling your own, so please take with a grain of salt: Depending on how frequently you need the random access get(i) and what performance you need from it (and how big your queue size will generally be), you could always use ArrayDeque.toArray()[i] when you need to access an element. The toArray() uses System.arraycopy() under the covers which should be pretty fast for small queue sizes and occasional usage. Would help to understand why you need random access to a queue and how often it is needed -- possibly there's a different way to implement your algorithm without it.
If it truly must be unbounded, then something like ConcurrentSkipListMap may be useful, if you assign an incrementing sequence to each event to use as the key in the map.
It provided methods such as pollFirst/LastEntry.
If you can sacrifice the unbounded nature of it, then a ring buffer maybe what you need.
A binomial heap can have O(1) amortized insert and O(log n) amortized delete min; I believe that it can also have O(log**2 n) amortized random access. Queue-push would insert the element into the heap, with successive integers as keys.
With a rbtree, you can do queue-push with O(log n) pessimistic for all of insert, delete min and random access. That is because the tree will have a contiguos set of integers as the keys, and the k-th element of the queue will be the element in the tree with the k-th key.
Related
What is the search performance of arrays, stacks and queues?
I think that arrays are the quickest and most straightforward, because I can access any element immediately by calling it using its index. Is this correct? What about the performance of stacks and queues? How do they compare?
Arrays (and collections based on arrays, eg. ArrayList) are bad for search performance because in the worst case you end up comparing every item (O(n)).
But if you don't mind modifying the order of your elements, you could sort the array (Arrays.sort(yourArray)) then use Arrays.binarySearch(yourArray, element) on it, which provides a O(log n) performance profile (much better that O(n)).
Stacks are in O(n), so nope.
Queues are not even meant to be iterated on, so looking for an object in here would mean consuming the whole queue, which is 1. not performant (O(n)) and 2. probably not what you want.
So among the datastructures you suggested, I would go for a sorted array.
Now, if you don't mind considering other datastructures, you really should take a look at those who use hash functions (HashSet, HashMap...).
Hash functions are really good at searching for elements, with a performance profile in O(1) (with a good hashcode() method in your objects).
I'll try to answer in a very simple way.
Stacks and queues are for storing data temporarily so that you can process the contents one by one. Just like a queue for buying movie tickets, or a stack of pancakes, you process one element at a time.
Arrays are for storing data as well as for accessing elements from the beginning, the end or in between. For searching, arrays would be a better choice.
Can you search elements inside stacks and queues? Possibly. But that's not what they are used for.
It depends how your search (or which search algorithm) is implemented. Stack or Queue may also helpful for some searching application like - BFS, DFS. But in normal case when you are using linear search you can consider about array or ArrayList.
In Java you have ArrayList (built on an array), a Stack (built on an array) and an ArrayQueue and ArrayDeque (which is also built on an array) As they all use the same underlying data structure their access speeds are basically the same.
For a brute force search, the time to scan or iterate over them (all of them support iteration) is O(n) Btw even a HashMap uses an array to store it's entries which is why iterating over its elements to find a value e.g. containsValue is O(n) as well.
While you could have a sorted array which would more naturally sit in an ArrayList, you could equally argue that a PriorityQueue will find and remove the next element the most efficiently. A Stack is ideal for finding the most recently added element.
To answer the question you have to determine what assumption the person asking the question is making. Without these further assumption you would have to say they could all be utilised. In that case I would use an ArrayList as it is the simplest to understand IMHO.
stack, queue and array all are three different and efficient data structures but as a bioinformatician if you want to store biological data, you should choose stack as data structure because last in and first out characteristic of recursive procedure shows that it is the most suitable data structure. Recursion is actually a characteristic of stack. At each procedure call a value can easily be pushed in it and can be retrieved when you exit from procedure. So it actually an aesy to use method.
See you can not compare one data structures with another. Each one has their own advantage and disadvantage.
Although array are good but you can not use them all the time because of their fixed size. They are use for inserting, deleting etc because they need O(1) time.
But when you want to access and insert data from one way only and don't want to perform searching, deleting in between you go for stack and queue. Stack and queue differ only in method of accessing element. In stack you access data from same side you enter data[LIFO] requires O(1) time. In queue you access data from other corner [FIFO]. Accessing elements in between can be done, but that's not what they are used for.
I'm returning large numbers of collections from a DTO object and was wondering if anyone could point me in right direction. Any type of collection will do, but I don't know which one is best suited for the task of returning a large number of objects.
I know this can change based on threading and the like, but I'm at least looking for general guidance and benchmarks. Also, I'm required to stay within standard Java collections (no third-party libraries).
As irreputable says: If you need a simple collection, than ArrayList should perform good because it is based on an Array which is fast by definition using the System functions.
If you set the initial capacity to a higher value (don't know what you call a large number), than it will be even faster because it reduces the amount of incremental reallocation.
Any other collection has some kind of an overhead like looking for hashcodes or beeing synchronized.
An ArrayList initialized at the correct size (if you know how many DTOs you'll be adding, or an upper bound) is the simplest and smallest Collection you'll find. By setting its size at initialization, it won't need to resize its internal array, an operation which produces garbage. It's better that directly using an array, which is really low level, and which you'd need to manage manually if it needs resizing (that's what the ArrayList does for you).
To create a pre-sized ArrayList, use the ArrayList(int capacity) constructor.
I'm a student and fairly new to Java. I was looking over the different speeds achieved by the two collections in Java, Linked List, and ArrayList. I know that an ArrayList is much much faster at looking up and placing in values into its indexes. My question is:
how can one make a linked list faster, if at all possible?
Thanks for any help.
zmahir
When talking about speed, perhaps you mean complexity. Insertion and retrieval operations for ArrayList (and arrays) are O(1), while for LinkedList they are O(n). And this cannot be changed - it is 'by definition'.
O(n) means that in order to insert an object at a given position, or retrieve it, you must traverse, in the worst case, all (n) the items in the list. Hence n operations. For ArrayList this is only one operation.
You probably can't. You don't know the size (well, ok you can), nor the location of each element. To find element 100 in a linked list, you need to start with item 1, find it's link to item 2, etc. until you find 100. This makes inserting into this list a tedious job.
There are many alternatives depending on your exact goals. You can use b-trees or similar methods to split the large linked list into smaller ones. Or use hashlists if you want to quickly find items. Or use simple arrays. But if you want a list that performs like an ArrayList, why not use an ArrayList?
You can split off regions which are linked to the main linked list, so this gives you entry points directly inside the list so you don't have to walk up to them. See the subList method here: http://download.oracle.com/javase/1.4.2/docs/api/java/util/AbstractList.html. This is useful if you have a number of 'sentences' made out of words, say. You can use a separate linked list to iterate over the sentences, which are sublists of the main linked list.
You can also use a ListIterator when adding, removing, or accessing elements. This helps greatly with increasing the speed of sequential access. See the listIterator method for this, and the class: http://download.oracle.com/javase/1.4.2/docs/api/java/util/ListIterator.html.
Speed of a linked list could be improved by using skip lists: http://igoro.com/archive/skip-lists-are-fascinating/
a linked list uses pointers to walk through the items, so for example if you asked for the 5th item, the runtime will start from the first item and walks through each pointer until it reaches the 5th item.
there is really not much you can do about it. a linked list may not be a good choice if you need fast acces to items. although there are some optimizations for it such as creating a circular linked list or a double linked list where you can walk back and forth the list but this really depends on the business logic and the application requirements.
my advise is to avoid linked lists if it does not match your needs and changing to a different data structure might be the best approach.
As a general rule, data structures are designed to do certain things well. LinkedLists are designed to be faster than ArrayLists at inserting elements and removing elements and about the same as ArrayLists at iterating across the list in order. When you change the way a LinkedList works, you make it no longer a true LinkedList, so there's not really any way to modify them to be faster at something and still be a LinkedList.
You'll need to examine the way you're using this particular collection and decide whether a LinkedList is really the best data structure for your purposes. If you share with us how you're using it, and why you need it to be faster, then we can advise you on which data structure you ought to consider using.
Lots of people smarter than you or I have looked at the implementation of the Java collection classes. If there were an optimization to be made, they would have found it and already made it.
Since the collection classes are pretty much as optimized as they can be, our primary task should be to choose the correct one.
When choosing your collection type, don't forget about things like HashSet. If order doesn't matter, and you don't need to put duplicates in the collection, then HashSet may be appropriate.
I'm a student and fairly new to Java. ... how can one make a linked list faster, if at all possible?
The standard Java collection type (indeed all data structures implemented in any language!) represent compromises on various "measures" such as:
The amount of memory needed to represent the data structure.
The time taken to perform various operations; e.g. for a "list" the operations of interest are insertion, removal, indexing, contains, iteration and so on.
How easy or hard it is to integrate / reuse the collection type; see below.
So for instance:
ArrayList offers lower memory overheads, fast indexing (O(1)), but slow contains, random insertion and removal (O(N)).
LinkedList has higher memory overheads, slow indexing and contains (O(N)), but faster removal (O(1)) under certain circumstances.
The various performance measures are typically determines by the maths of the various data structures. For example, if you have a chain of nodes, the only way to get the ith node is to step through them from the beginning. This involves following i pointers.
Sometimes you can modify the data structures to improve one aspect of the performance. But this typically comes at the cost of some other aspect of the performance. (For example, you could add a separate index to make indexing of a linked list faster. But the cost of maintaining the index on insertion / deletion would mean that you'd probably be better of using an ArrayList.)
In some cases the integration / reuse requirements have significant impact on performance.
For example, it is theoretically possible to optimize a linked list's space usage by adding a next field to the list element type, combining the element and node objects and saving 16 or so bytes per list entry. However, this would make the list type less general (the member/element class would need to implement a specific interface), and has the restriction that an element can belong to at most one list at any time. These restrictions are so limiting that this approach is rarely used in Java.
For a second example, consider the problem of inserting at a given position in a linked list. For the LinkedList class, this is normally an O(N) operation, because you have to step through the list to find the position. In theory, if an application could find and remember a position, it should be able to perform the insertion at that position in O(1). Unfortunately, neither the List APIs provides no way to "remember" a position.
While neither of these examples is a fundamental roadblock to a developer "doing his own thing", they illustrate that using general data structure APIs and general implementations of those APIs has performance implications, and therefore represents a trade-off between performance and ease-of-use.
I'm a bit surprised by the answers here. There are big difference between the theoretical performance of LinkedLists and ArrayLists compared to the actual performance of the Java implementations.
What makes the Java LinkedList slower than a theoretical LinkedList is that it does a lot more than just the operations. For example it checks for concurrent modifications and other safeties.
If you know your use case, you can write a your own simple implementation of a LinkedList and it will be much faster.
I have specific requirements for the data structure to be used in my program in Java. It (Data Structure) should be able to hold large amounts of data (not fixed), my main operations would be to add at the end, and delete/read from the beginning (LinkedLists look good soo far). But occasionally, I need to delete from the middle also and this is where LinkedLists are soo painful. Can anyone suggest me a way around this? Or any optimizations through which I can make deletion less painful in LinkedLists?
Thanks for the help!
A LinkedHashMap may suit your purpose
You'd use an iterator to pull stuff from the front
and lookup the entry by key when you needed to access the middle of the list
LinkedList falls down on random accesses. Deletion, without the random access look up, is constant time and so really not too bad for long lists.
ArrayList is generally fast. Inserts and removes from the middle are faster than you might expect because block memory moves are surprisingly fast. Removals and insertions near the start to cause all the following data to be moved down or up.
ArrayDeque is like ArrayList only it uses a circular buffer and has a strange interface.
Usual advice: try it.
you can try using linked list with a pointers after evey 10000th element so that you can reduce the time to find the middle which you wish to delete.
here are some different variations of linked list:
http://experimentgarden.blogspot.com/2009/08/performance-analysis-of-thirty-eight.html
LinkedHashMap is probably the way to go. Great for iteration, deque operations, and seeking into the middle. Costs extra in memory, though, as you'll need to manage a set of keys on top of your basic collection. Plus I think it'll leave 'gaps' in the spaces you've deleted, leading to a non-consecutive set of keys (shouldn't affect iteration, though).
Edit: Aha! I know what you need: A LinkedMultiSet! All the benefit of a LinkedHashMap, but without the superfluous key set. It's only a little more complex to use, though.
First you need to consider whether you will delete from the center of the list often compared to the length of the list. If your list has N items but you delete much less often than 1/N, don't worry about it. Use LinkedList or ArrayDeque as you prefer. (If your lists are occasionally huge and then shrink, but are mostly small, LinkedList is better as it's easy to recover the memory; otherwise, ArrayDeque doesn't need extra objects, so it's a bit faster and more compact--except the underlying array never shrinks.)
If, on the other hand, you delete quite a bit more often than 1/N, then you should consider a LinkedHashSet, which maintains a linked list queue on top of a hash set--but it is a set, so keep in mind that you can't store duplicate elements. This has the overhead of LinkedList and ArrayDeque put together, but if you're doing central deletes often, it'll likely be worth it.
The optimal structure, however--if you really need every last ounce of speed and are willing to spend the coding time to get it--would be a "resizable" array (i.e. reallocated when it was too small) with a circular buffer where you could blank out elements from the middle by setting them to null. (You could also reallocate the buffer when too much was empty if you had a perverse use case then.) I don't advise coding this unless you either really enjoy coding high-performance data structures or have good evidence that this is one of the key bottlenecks in your code and thus you really need it.
I need a class that implements Iterable, and does not need to be safe for concurrent usage. Of the various options, such as LinkedList, HashSet, ArrayList etc, which is the lightest-weight?
To clarify the use-case, I need to be able to add a number of objects to the Iterable (typically 3 or 4), and then something else needs to iterate over it.
ArrayList. From the Javadoc
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.
That entirely depends on what you mean by "lightest weight". What operations do you need to do, and how often? Do you know the final size beforehand? Are you trying to save execution time or memory?
I would agree that zkarthik that ArrayList is very often a good choice... but it will behave very badly if you want to create a large collection and then repeatedly remove the first element, for example. There's a good reason for there being so many different collections: they have different performance characteristics for different situations.
They all have very different features and behavior, so you should base your choice on how you will use them. For example, for random access and high locality, use an ArrayList; if you need fast unordered insertion and querying, use a HashSet.
If by 'lightweight', you mean 'best performance' then the question is almost impossible to answer without understanding how the collection will be used. All you've told us so for is that it doesn't need to support concurrent usage, but in order to have any hope of answering the question we'd need to know things like
How many objects will be stored in the collection (on average)
What is the relative frequency of read and write access
Is random-access required
Is ordered access required
A number of people have suggested ArrayList may be best. However, I seem to recall reading (possibly in Effective Java 2nd edition), that for certain patterns of usage, Queue performs better than List, because it does not incurr the penalty of random access. In other words, you can add/remove items from a List in any order, but you can only add/remove items in a queue in a specific order (i.e. add to the tail, and remove from the head).