Browse Learn Clojure Foundations as a Java Developer

Collections

Choose the right Clojure collection as a Java engineer: vectors for indexed ordered data, maps for domain records, sets for membership, lists for code-shaped sequences, and seqs for generic traversal.

Clojure’s core data structures are immutable persistent collections. That phrase is worth learning early:

  • Immutable: operations do not modify a collection in place.
  • Persistent: updates return a new collection while sharing structure with the old one, so value-oriented updates are practical in real systems.

Java mental model: instead of mutating an ArrayList, HashMap, or HashSet, you usually produce a new value and pass it forward. That makes tests, concurrency, and review easier.

The Big Four Plus Seqs

Collection Literal Default use Java comparison
Vector [1 2 3] Ordered indexed data Immutable cousin of ArrayList
Map {:id 42} Domain records and lookup tables Immutable cousin of HashMap
Set #{:a :b} Membership and uniqueness Immutable cousin of HashSet
List '(1 2 3) Code forms and head-first sequences More like a persistent linked list
Seq no single literal Generic traversal abstraction Similar intent to Iterable, but value-oriented and often lazy

Practical Defaults

  • Use vectors for most ordered data.
  • Use maps for records, configuration, and structured domain values.
  • Use sets for membership checks and deduplication.
  • Use lists mostly when working with code-as-data or head-first sequence algorithms.
  • Use sequence functions such as map, filter, and reduce across all of them.

Gotchas Worth Memorizing

Gotcha Example Why it matters
conj is collection-specific (conj [1 2] 3) returns [1 2 3]; (conj '(1 2) 3) returns (3 1 2) It adds where the collection is efficient
contains? checks keys or indexes (contains? [10 20] 20) is false For vectors, keys are indexes
Many transforms return lazy seqs (map inc [1 2 3]) returns a seq, not a vector Use mapv, into, or vec when you need a vector
Updates return new values (assoc m :x 1) does not mutate m Bind or return the new value
    flowchart TD
	    A["Need a collection"] --> B{"Ordered by position?"}
	    B -->|Yes| C["Vector"]
	    B -->|No| D{"Key-value structure?"}
	    D -->|Yes| E["Map"]
	    D -->|No| F{"Membership or uniqueness?"}
	    F -->|Yes| G["Set"]
	    F -->|No| H{"Code form or head-first sequence?"}
	    H -->|Yes| I["List"]
	    H -->|No| J["Use seq functions over existing data"]

The goal of this section is to make you fluent at reading collection literals, predicting what common operations return, and choosing the default collection that keeps your code simple.

In this section

  • Lists in Clojure
    Understand Clojure lists as immutable head-first sequences, code forms, and occasional data structures, while avoiding Java List assumptions about indexed access.
  • Vectors in Clojure
    Use Clojure vectors as the default ordered collection for indexed, immutable data, with practical guidance on conj, assoc, subvec, sequence functions, and Java ArrayList comparisons.
  • Maps in Clojure
    Use Clojure maps as immutable records and lookup tables with keyword keys, assoc, update, dissoc, merge, nested updates, and Java HashMap comparisons.
  • Sets in Clojure
    Use Clojure sets for uniqueness, membership checks, set algebra, deduplication, and Java Set comparisons while preserving immutable value semantics.
Revised on Saturday, May 23, 2026