Browse Clojure Foundations for Java Developers

Collection Manipulation

The everyday update operations for persistent collections: get/assoc/update/conj plus dissoc/disj/into and nested helpers.

In Clojure, collections are persistent and immutable: every “update” returns a new value (usually sharing structure with the old one). This makes code easier to reason about and safer under concurrency than the default Java collections model.

The Core Operations You’ll Use Daily

Read: get (and keyword lookup)

1(def m {:a 1 :b 2})
2
3(get m :a)  ; => 1
4(:a m)      ; => 1

Write: assoc (maps and vectors)

1(assoc {:a 1} :b 2)      ; => {:a 1, :b 2}
2(assoc [10 20 30] 1 99)  ; => [10 99 30]

Update: update (change a key’s value with a function)

1(update {:a 1} :a inc)                 ; => {:a 2}
2(update {:a [1 2]} :a conj 3)          ; => {:a [1 2 3]}

Add: conj (adds in the “natural” place)

1(conj [1 2] 3)    ; => [1 2 3]   ; vector: add at end
2(conj '(1 2) 3)   ; => (3 1 2)   ; list: add at front
3(conj #{1 2} 3)   ; => #{1 2 3}  ; set: add element
4(conj {:a 1} [:b 2]) ; => {:a 1, :b 2} ; map: add entry

Remove / Merge / Build

  • dissoc — remove map keys: (dissoc {:a 1 :b 2} :b)

  • disj — remove set elements: (disj #{1 2 3} 2)

  • merge — combine maps (rightmost wins): (merge {:a 1} {:a 2 :b 3})

  • into — build a collection from another collection/seq:

    1(into [] (range 5))    ; => [0 1 2 3 4]
    2(into #{} [1 1 2 3])   ; => #{1 2 3}
    

Nested Helpers

1(get-in {:a {:b 1}} [:a :b])                 ; => 1
2(assoc-in {} [:a :b] 1)                      ; => {:a {:b 1}}
3(update-in {:a {:b 1}} [:a :b] + 10)         ; => {:a {:b 11}}

Java-Engineer Gotcha: contains?

contains? checks key/index membership, not “contains this value?”

1(contains? {:a 1} :a)      ; => true    ; key exists
2(contains? [:a :b] 1)      ; => true    ; index 1 exists
3(contains? [:a :b] :b)     ; => false   ; :b is not an index

Use some (or set membership) when you want “does this value appear?”

Knowledge Check: Collection Updates

### What does `(contains? [:a :b] 1)` return, and why? - [x] `true`, because `contains?` checks whether index `1` exists in the vector. - [ ] `true`, because `:b` is present as a value. - [ ] `false`, because vectors can’t be used with `contains?`. - [ ] It throws because `1` is not a keyword. > **Explanation:** On vectors, `contains?` answers “is this a valid index?”—not “is this value in the vector?” ### What does `(assoc [10 20 30] 1 99)` evaluate to? - [x] `[10 99 30]` - [ ] `[99 10 20 30]` - [ ] `(10 99 30)` - [ ] It mutates the vector and returns `nil`. > **Explanation:** Vectors support associative update by index. `assoc` returns a new vector with the index updated. ### What’s the key property of `update` on maps? - [x] It returns a new map by applying a function to the current value at a key. - [ ] It mutates the map in place. - [ ] It updates all keys at once. - [ ] It only works for numeric values. > **Explanation:** `update` is the functional “modify this field” operation: it reads the old value, computes a new one, and returns an updated map.
Revised on Friday, April 24, 2026