Reputation: 980
In Java, let's say I have an integer array: int[] a = {1, 2, 3, 4, 5};
.
If I want to change an element in the array, I can do so by changing the data at a certain address in memory: a[2] = 9;
=> {1, 2, 9, 4, 5}
.
In Clojure, I can have a vector: (def a [1 2 3 4 5])
.
How do I change an element at a certain position in the vector with a guaranteed worst case time complexity of O(1)? I have read that the assoc
keyword has O(1) average time complexity, but this is not what I am looking for. Also, I looked at transient vectors, but I have yet to find a good and simple example of updating a vector in O(1).
Upvotes: 1
Views: 1043
Reputation: 6061
Clojure vectors, in their current implementation, have a complexity of O(log_32(n))(logarithm in base 32). Mathematically, O(log_32(n)) is the same thing as O(log(n)). The differences are not theoretical but practical:
Upvotes: 6
Reputation: 20194
In Clojure a vector is a specific data type - it is immutable and has O(log_32(n)) update, returning a new vector that will usually share structurally with the original.
If you need O(1) update, you can use an Array, all of Java's data types are usable from Clojure. I use into
here just to have an easy to read representation in the repl - each usage creates a new vector, so you probably want to avoid this in your performance sensitive code.
+user=> (def a (into-array Object [:a 1 :b "m" (java.util.Date.)]))
#'user/a
+user=> a
#object["[Ljava.lang.Object;" 0x456d6c1e "[Ljava.lang.Object;@456d6c1e"]
+user=> (into [] a)
[:a 1 :b "m" #inst "2016-06-11T20:28:05.230-00:00"]
+user=> (aset a 2 'new-contents)
new-contents
+user=> (into [] a)
[:a 1 new-contents "m" #inst "2016-06-11T20:28:05.230-00:00"]
There are a variety of functions defined for working with arrays in Clojure.
Upvotes: 4