I'm not sure how you would get O(1) append and O(1) random access unless you include another data structure.
Typically, if you want to be able to append elements, you can either copy the source collection, which keeps O(1)
random access but gives you O(n)
append; or you can do what Eric did, and retain the old list segment(s), which gives you O(1)
append time but O(n)
random access. Assuming the constant append time is critical, that leaves you with the option of incorporating a second data structure to provide constant-time random access.
The Scala documentation claims "effectively constant" add and lookup times for its immutable HashMap. If true, I suggest looking at their implementation. You could take a solution like Eric's and add an efficient immutable map of indexes to the elements themselves. This would add a bit of memory overhead, though, and while append operations would be efficient, insertions would not.
I am, however, a bit skeptical of the Scala HashMap performance claims. Other immutable map implementations claim log32(n)
complexity, which presumably applies to both add and lookup operations. My gut tells me that you're not going to get better than logarithmic complexity, though log32(n)
is pretty reasonable.