https://github.com/slk500/clojure-collections-comparison is open for MR.
legend:
- ‘1’ means minimal data provided e.g (list 1), (vector 1), (hash-map :a 1)
- ‘coll’ is one of data type: list, vector, hash-set, sorted-set, hash-map. Because everyone of them is a collection.
item | list | vector | hash-set | sorted-set | hash-map | sorted-map |
---|---|---|---|---|---|---|
“literal syntax” | () | [ ] | #{} | #{} | {} | {} |
create from args | (list 1 2 3) | (vector 1 2 3) | (hash-set 2 3 1) | (sorted-set 1 2 3) | (hash-map :b 2 :c 3 :a 1) | (sorted-map :a 1 :b 2 :c 3) |
create from collection | (apply list [1 2 3]) | (vec ‘(1 2 3)) | (set ‘(2 3 1)) | (apply sorted-set [2 3 1]) | (into (hash-map) {:a 1 :b 2 :c 3}) | (into (sorted-map) {:a 1 :b 2 :c 3}) |
(coll? coll) | true | true | true | true | true | true |
(sequential? coll) | true | true | false | false | false | false |
(associative? coll) | false | true | false | false | true | true |
(type coll) | PersistentList$EmptyList | PersistentVector | PersistentHashSet | PersistentTreeSet | PersistentArrayMap | PersistentTreeMap |
(type (coll 1)) | PersistentList | PersistentVector | PersistentHashSet | PersistentTreeSet | PersistentArrayMap | PersistentTreeMap |
(list? coll) | true | false | false | false | false | false |
(vector? coll) | false | true | false | false | false | false |
(set? coll) | false | false | true | true | false | false |
(map? coll) | false | false | false | false | true | true |
(seq? coll) | true | false | false | false | false | false |
(seq? (coll 1)) | true | false | false | false | false | false |
(seq? (seq coll)) | false | false | false | false | false | false |
(seq? (seq (coll 1)) | true | true | true | true | true | true |
(type (seq coll)) | nil | nil | nil | nil | nil | nil |
(type (sequence coll) | PersistentList$EmptyList | PersistentList$EmptyList | PersistentList$EmptyList | PersistentList$EmptyList | PersistentList$EmptyList | PersistentList$EmptyList |
(type (sequence (coll 1))) | PersistentList | PersistentVector$ChunkedSeq | APersistentMap$KeySeq | APersistentMap$KeySeq | PersistentHashMap$NodeSeq | PersistentTreeMap$Seq |
(type (seq (coll 1))) | PersistentList | PersistentVector$ChunkedSeq | APersistentMap$KeySeq | APersistentMap$KeySeq | PersistentHashMap$NodeSeq | PersistentTreeMap$Seq |
“unique elements” | false | false | true | true | true (only keys) | true (only keys) |
“same order of elements” | true | true | false | true | false | true |
“read” | nth | get, IFn, nth | get, IFn, key | get, IFn, key | ||
(get coll 1) | nil | nil | nil | nil | nil | nil |
(get (coll 1) 1) | nil | true (index) | useless | useless | true (key) | true (key) |
(get nil 1) | nil | nil | nil | nil | nil | nil |
“get out of range” | nil or not-found | nil or not-found | nil or not-found | nil or not-found | nil or not-found | nil or not-found |
“IFn” | error | ([:a :b :c] 1) => :b | error | error | ({:b 2 :c 3 :a 1} :b) => 2 | ({:a 1 :b 2 :c 3} :a) => 1 |
“IFn out of range” | error | error | error | error | nil | nil |
“nth” | true | true | true | true | error | error |
(nth nil 1) | nil | |||||
“nth out of range” | ||||||
“add” | cons, conj | assoc | assoc | |||
“conj (coll)” | front | back | vary | vary | vary | vary |
“cons (seq)” | front | front | vary | vary | vary | vary |
“remove” | disj | dissoc | ||||
“contains?” | error | true (index) | true (element) | true (element) | true (key) | true (key) |
(type '()) ;=> PersistentList$EmptyList
(apply list [1 2 3]) ;=> (1 2 3)
(apply sorted-set [2 3 1]) ;=> #{1 2 3}
(into (hash-map) {:a 1 :b 2}) ;=> {:a 1, :b 2}
(into (sorted-map) {:b 2 :c 3 :a 1}) ;=> {:a 1, :b 2, :c 3}
(coll? (list)) ; => true
(coll? (vector)) ; => true
(coll? (hash-set)) ; => true
(coll? (sorted-set)) ; => true
(coll? (hash-map)) ; => true
(coll? (sorted-map)) ; => true
Definitions from Oxford Languages: sequential - forming or following in a logical order or sequence.
(sequential? (list)) ;=> true
(sequential? (vector)) ;=> true
(sequential? (hash-set)) ;=> false
(sequential? (sorted-set)) ;=> false
(sequential? (hash-map)) ;=> false
(sequential? (sorted-map)) ;=> false
I was thinking that sorted-set & sorted-map are (= sequential? true) They have logical order (they are sorted) so why they are not sequential?
dgb23 hashed collections have sequence representations (map entries) that are sequential. I think it is more of an implementation thing. In theory you’re right, they are both sequential and hashed collections.
phill The sequential? docstring tells me nothing about what it does! I do not see a basis for expectation of any particular return value. It would be a good question for ask.clojure.org so it might get clarified. However, it would be normal for sequential? to mean “preserves the order of insertion?” which vectors do (expect true), lists do in reverse (expect -true), and sets and maps never do (expect false). (edited)
dgb23 Sequential is an empty interface. I think it’s just a signal that is put on certain implementations.
Returns true if coll implements Associative(associative? (list)) ;=> false
(associative? (vector)) ;=> true
(associative? (hash-set)) ;=> false
(associative? (sorted-set)) ;=> false
(associative? (hash-map)) ;=> true
(associative? (sorted-map)) ;=> true
(type (list)) ;=> Persistentlist$EmptyList
(type (vector)) ;=> PersistentVector
(type (hash-set)) ;=> PersistentHashSet
(type (sorted-set)) ;=> PersistentTreeSet
(type (hash-map)) ;=> PersistentArrayMap
(type (sorted-map)) ;=> PersistentTreeMap
(type (list 1)) ;=> Persistentlist
(type (vector 1)) ;=> PersistentVector
(type (hash-set 1)) ;=> PersistentHashSet
(type (sorted-set 1)) ;=> PersistentTreeSet
(type (hash-map :a 1)) ;=> PersistentHashMap
(type (sorted-map :a 1)) ;=> PersistentTreeMap
(list? (list)) ;=> true
(list? (vector)) ;=> false
(list? (hash-set)) ;=> false
(list? (sorted-set)) ;=> false
(list? (hash-map)) ;=> false
(list? (sorted-map)) ;=> false
(vector? (list)) ;=> false
(vector? (vector)) ;=> true
(vector? (hash-set)) ;=> false
(vector? (sorted-set)) ;=> false
(vector? (hash-map)) ;=> false
(vector? (sorted-map)) ;=> false
(set? (list)) ;=> false
(set? (vector)) ;=> false
(set? (hash-set)) ;=> true
(set? (sorted-set)) ;=> true
(set? (hash-map)) ;=> false
(set? (sorted-map)) ;=> false
(map? (list)) ;=> false
(map? (vector)) ;=> false
(map? (hash-set)) ;=> false
(map? (sorted-set)) ;=> false
(map? (hash-map)) ;=> true
(map? (sorted-map)) ;=> true
(seq? (list)) ;=> true
(seq? (vector)) ;=> false
(seq? (hash-set)) ;=> false
(seq? (sorted-set)) ;=> false
(seq? (hash-map)) ;=> false
(seq? (sorted-map)) ;=> false
(seq? (list 1)) ;=> true
(seq? (vector 1)) ;=> false
(seq? (hash-set 1)) ;=> false
(seq? (sorted-set 1)) ;=> false
(seq? (hash-map :a 1)) ;=> false
(seq? (sorted-map :a 1)) ;=> false
(seq? (seq (list))) ;=> false
(seq? (seq (vector))) ;=> false
(seq? (seq (hash-set))) ;=> false
(seq? (seq (sorted-set))) ;=> false
(seq? (seq (hash-map))) ;=> false
(seq? (seq (sorted-map))) ;=> false
(seq? (seq (list 1))) ;=> true
(seq? (seq (vector 1))) ;=> true
(seq? (seq (hash-set 1))) ;=> true
(seq? (seq (sorted-set 1))) ;=> true
(seq? (seq (hash-map :a 1))) ;=> true
(seq? (seq (sorted-map :a 1))) ;=> true
Returns a seq on the collection. If the collection is empty, returns nil. (seq nil) returns nil. seq also works on Strings, native Java arrays (of reference types) and any objects that implement Iterable. Note that seqs cache values, thus seq should not be used on any Iterable whose iterator repeatedly returns the same mutable object.
(type (seq (list))) ;=> nil
(type (seq (vector))) ;=> nil
(type (seq (hash-set))) ;=> nil
(type (seq (sorted-set))) ;=> nil
(type (seq (hash-map))) ;=> nil
(type (seq (sorted-map))) ;=> nil
(type (sequence (list))) ;=> PersistentList$Emptylist
(type (sequence (vector))) ;=> PersistentList$Emptylist
(type (sequence (hash-set))) ;=> PersistentList$Emptylist
(type (sequence (sorted-set))) ;=> PersistentList$Emptylist
(type (sequence (hash-map))) ;=> PersistentList$Emptylist
(type (sequence (sorted-map))) ;=> PersistentList$Emptylist
(type (sequence (list 1))) ;=> PersistentList
(type (sequence (vector 1))) ;=> PersistentVector$ChunkedSequence
(type (sequence (hash-set 1))) ;=> APersistentMap$KeySequence
(type (sequence (sorted-set 1))) ;=> APersistentMap$KeySequence
(type (sequence (hash-map :a 1))) ;=> PersistentHashMap$NodeSequence
(type (sequence (sorted-map :a 1))) ;=> PersistentTreeMap$Sequence
Returns a seq on the collection. If the collection is empty, returns nil. (seq nil) returns nil. seq also works on Strings, native Java arrays (of reference types) and any objects that implement Iterable. Note that seqs cache values, thus seq should not be used on any Iterable whose iterator repeatedly returns the same mutable object.
(type (seq (list 1))) ;=> Persistentlist
(type (seq (vector 1))) ;=> PersistentVector$ChunkedSeq
(type (seq (hash-set 1))) ;=> APersistentMap$KeySeq
(type (seq (sorted-set 1))) ;=> APersistentMap$KeySeq
(type (seq (hash-map :a 1))) ;=> PersistentHashMap$NodeSeq
(type (seq (sorted-map :a 1))) ;=> PersistentTreeMap$Seq
You cannot use the get function with a list to retrieve by index.
([map key] [map key not-found])(get (list) 1) ;=> nil
(get (vector) 1) ;=> nil
(get (hash-set) 1) ;=> nil
(get (sorted-set) 1) ;=> nil
(get (hash-map) :a) ;=> nil
(get (sorted-map) :a) ;=> nil
(get (list :a :b) 0) ;=> nil
(get (list :a :b) :a) ;=> nil
(get (list :a :b) "string") ;=> nil
; Although lists are sequences, they are not keyed sequences.
(get (vector :a :b) 0) ;=> :a
(get (vector :a :b) 1) ;=> :b
(get (hash-set :a :b) 0) ;=> nil
(get (hash-set :a :b) 1) ;=> nil
(get (hash-set :a :b) :a) ;=> :a
(get (hash-set :a :b) "string") ;=> nil
(get (sorted-set :a :b) 0) ;=> Unhandled java.lang.ClassCastException
(get (sorted-set :a :b) 1) ;=> Unhandled java.lang.ClassCastException
(get (sorted-set :a :b) "string") ;=> Unhandled java.lang.ClassCastException
(get (sorted-set :a :b) :a) ;=> :a
(get (sorted-set :a :b) :b) ;=> :a
(get (hash-map :a 1 :b 2) :a) ;=> 1
(get (hash-map :a 1 :b 2) 1) ;=> nil
(get (sorted-map :a 1 :b 2) :a) ;=> 1
(get (sorted-map :a 1 :b 2) 1) ;=> ;=> Unhandled java.lang.ClassCastException
(get nil 1) ; => nil
('(1 2 3) 1) ; class clojure.lang.PersistentList cannot be cast to class clojure.lang.IFn (clojure.lang.PersistentList and clojure.lang.IFn
([1 2 3] 1) ;=> 2
(#(1 2 3) 2) ;=> error
‘IFn’ means ‘Interface Function’. Keywords also have this interface. In the preceding examples, we can see that a list that is not quoted with ’ throws an error unless the first item of the list can be invoked as a function.
({:a 1 :b 2 :c 3} :a); => 1 | maps are functions of their keys
(:a {:a 1 :b 2 :c 3}) ; => 1 | keywords are also functions
(1 [:b :c :a]) ;=> error
([:b :c :a] 1) ;=> :c
(:c [:b :c :a]) ;=> nil
(nil 0) ; => IllegalArgumentException
([:a :b] 2) ;=> IndexOutOfBoundsException
({:a 1 :b 2} :c); => nil
Using nth to retrieve an element from a list is slower than using get to retrieve an element from a vector.
(nth (list :a :b) 0) ;=> :a
(nth (list :a :b) 1) ;=> :b
(nth (list :a :b) 3) ;=> Unhandled java.lang.IndexOutOfBoundsException
(nth (vector :a :b) 0) ;=> :a
(nth (vector :a :b) 1) ;=> :b
(nth (hash-set :a :b) 0) ;=> Unhandled java.lang.UnsupportedOperationException
(nth (sorted-set :a :b) 0) ;=> Unhandled java.lang.UnsupportedOperationException
(nth (hash-map :a 1 :b 2) 0) ;=> Unhandled java.lang.UnsupportedOperationException
(nth nil 1) ; => nil
(conj [1 2 3] 4) ; => [1 2 3 4]
(cons "two" (list "first")) ;=> ("two" "first")
(cons "two" (vector "first")) ;=> ("two" "first")
(cons "two" (hash-set "first")) ;=> ("two" "first")
(cons "two" (sorted-set "first")) ;=> ("two" "first")
(contains? '(1 2 4 3) 4)
;=> IllegalArgumentException
(contains? [1 2 3 4] 0) ;=> true
(contains? [1 2 3 4] 4) ;=> false
(contains? #{1 2 3 4} 0) ;=> false
(contains? #{1 2 3 4} 4) ;=> true
(contains? {:a 1 :b 2} :a) ;=> true
(contains? {:a 1 :b 2} 1) ;=> true