I want to implement a very simple sliding window. In other words, I will have some kind of list with objects inserted from the right end of that list and dropped from the left end. In every insertion, the previous objects are left-shifted by one index. When the list get filled with objects, in every insertion from the right end an object will be dropped from the left end (and the previous objects of course will be left-shifted by one index, as usual).
I had in mind either a LinkedList or an ArrayDeque - probably the latter is a better choise, since as far as I know both inserting AND removing to/from either end is constant effort O(1) for an ArrayDeque, which is not the case for a LinkedList. Is that right?
Moreover, I would like to ask the following: Left-shifting all the previous objects stored in the sliding window when I insert a new object is processing-intensive for a large sliding window with 100,000 or even 1,000,000 objects as in my case. Is there any other data structure which might perform better in my application?
NOTE: I use the term "sliding window" for what I want to implement, maybe there is some other term that describes it better, but I think is clear what I want to do from the above description.
ArrayDeque does what you want. It doesn't move the elements around. It moves the index of where the start and the end is. When you add an element, the end counter moves and when you remove an element, the start counter moves.
One advantage of ArrayDeque is that it can use less memory and does create garbage. On the down side it has a fixed maximum size. LinkedList grows and shrinks.
BTW If you want a light weight sliding window or the average of some values, an exponentially weighted moving average is much cheaper as you only need to record two values, the previous and last time.
e.g
double last = 0;
long lastTime = 0;
double halfLife = 60 * 1000; // 60 seconds for example.
public static double ewma(double sample, long time) {
double alpha = Math.exp((lastTime - time) / halfLife);
lastTime = time;
return last = sample * alpha + last * (1 - alpha);
}
or you can approximate this to avoid calling Math.exp with
public static double ewma(double sample, long time) {
long delay = time - lastTime
double alpha = delay >= halfLife ? 1.0 : delta / halfLife;
lastTime = time;
return last = sample * alpha + last * (1 - alpha);
}
This is many times faster and for short intervals gives much the same result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With