2

Currently, the "growing" algorithm figures out that the Array backing the ArrayList/ArrayBuffer is too small for the requested operation and copies the contents to the beginning of a larger array.

jsuereth explains it very well in the comments of this thread:

ArrayBuffer is great for append but not as good for prepend. Java's ArrayList will actually try to amortize costs to prepend as well, making it slightly better in my opinion. Yes ArrayBuffer is probably good enough if you're just appending on to a list and indexing elements.

Wouldn't it be a good enhancement to make the location of the old contents depend on the last operation, based on the assumption that this operation might be called more often in the future?

I. e.:

  • if append needs a larger array, copy the existing contents to the front of the new array:

    [x|x|x|x|x|x] 
           |
           v
    [x|x|x|x|x|x| | | | | ]
    
  • if prepend needs a larger array, copy the existing contents to the back of the new array:

    [x|x|x|x|x|x] 
           |
           v
    [ | | | | |x|x|x|x|x|x]
    

Will this solve the performance problems for prepend, while generally making the algorithm a bit more adaptive to usage patterns? (Worst case would be alternatively appending/prepending large stuff ...)

Are there any other data structures which already take the last operation into account when growing the underlying structure?

5
  • 3
    If you need such a data structure, please be my guest. Or maybe you should use a LinkedList instead. Commented May 31, 2011 at 12:02
  • 1
    Maybe the "Wouldn't it be a good enhancement [...]" or the "Will this solve [...]" parts? Commented May 31, 2011 at 12:05
  • The first is very subjective and the second very localized. "Wouldn't it be a good enhancement?" is a discussion-question, for which SO isn't well-suited. "Will this solve [...]?" is a very-specific question to which the answer is "try it". Commented May 31, 2011 at 12:07
  • I guess we have some WP admins here. :-) Commented May 31, 2011 at 12:09
  • It's not about enforcing some arbitrary standards (not that WP admins ever do that!), but about choosing the appropriate venue. This is probably better suited as a bug report (ideally with a patch!) to the OpenJDK. Commented May 31, 2011 at 12:12

4 Answers 4

4

Perhaps what you need is ArrayDeque. This has an O(1) operation for append and prepend (unless the capacity is changed)

This has an array where it has a index to the head and tail which allows it to write the start or end position without having to shuffle all the entries down/up.

Sign up to request clarification or add additional context in comments.

10 Comments

This sound like pretty much what I imagined. Does the growing also take the requested operation into account? Or will the old array just copied to the middle of the new one?
The expense of the operation doesn't depend on the position of the data so there is no advantage is arranging the data from a particular point. It happens to copy the data so the head = 0, but this is not a requirement.
Yes, it might be asymptomatically the same, but if I always prepend, it requires far more growing operations than taking the last operation into account.
Where do you get "if I always prepend, it requires far more growing operations"? I repeat, "This has an O(1) operation for append and prepend" They cost the same regardless of position. This is the whole point of suggesting this class.
My question is specially focused on the performance problems when growing the underlying array. I know that both head and tail "normally" have O(1). I thought that was perfectly clear...
|
3

In the general sense, MOST pre-defined structures and algorithms are based on some assumption of the most common use-cases. As it's impossible to create a "general" implementation that covers every possible scenario, there will always be some outside cases where the approach is less than optimal.

If your particular use-case is performance-critical enough that this is a problem, my suggestion is to create your own Array implementation, tailored to your usage. Beware the sub-optimization devil though. Rarely it's actually worth the increased cost of maintenance to save those few odd CPU cycles or bytes of memory.

Comments

2

You can use ArrayDeque for an array-backed data structure with fast prepend.

Comments

2

If you're not going to do a lot of lookups, and just be doing linear traversals, then go for the UnrolledBuffer - an unrolled linked list implementation. Otherwise, a Vector and its +: should be an efficient choice.

1 Comment

Interesting. And thanks for letting me know that this class exists .. I have never seen it before!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.