# DataStructures.jl fills in the containers Julia's standard library leaves out

> DataStructures.jl is the JuliaCollections package that supplies the data structures the standard library does not, from deques and priority queues to three different balanced tree implementations and three different hash table designs. Several of the entries exist in more than one mutable and immutable variant, and a few name the technique they are built on, which is how you choose between them.

**JuliaCollections/DataStructures.jl** — Julia implementation of Data structures

- Repository: https://github.com/JuliaCollections/DataStructures.jl
- Website: https://juliacollections.github.io/DataStructures.jl/dev/
- Stars: 747 · Forks: 261
- Language: Julia
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/juliacollections-datastructures-jl

## The list is long because the standard library is small

DataStructures.jl is described simply as a Julia implementation of data structures, and the package implements a variety of them.

The list is long enough to be worth reading as a map of what the Julia standard library leaves out. The linear and queue-like structures come first: Deque, implemented with an unrolled linked list, CircularBuffer, CircularDeque which is based on a circular buffer, Stack, Queue, and Priority Queue.

Then the counting and set structures: Fenwick Tree, Accumulators and Counters, described as Multisets and Bags, Disjoint-Sets, Binary Heap, Mutable Binary Heap, and Ordered Dicts and Sets.

The hash tables are the part with real variety. There is a RobinDict implemented with Robin Hood Hashing, a SwissDict inspired from SwissTables, and Dictionaries with Defaults.

After that come the string and integer structures: Trie, Linked List and Mutable Linked List, Sorted Dict, Sorted Multi-Dict and Sorted Set, DataStructures.IntSet, SparseIntSet, and DiBitVector, in which each element can store two bits.

And finally the trees: Red Black Tree, AVL Tree, and Splay Tree.

Twenty-four entries, and the notable thing is not the count but the duplication. Stack and Queue appear next to Deque and CircularDeque. Binary Heap and Mutable Binary Heap are separate. Linked List has a mutable twin. That is the package's main design decision visible from the outside, and it is the one that determines whether you pick the right name.

## The names tell you which technique you are getting

Several entries in the list name the algorithm they are built on, and those are the ones where a choice is genuinely being offered rather than a gap being filled.

The Deque uses an unrolled linked list. That is a linked list with a small array at each node, which cuts the pointer chasing per element at the cost of a little memory, and it is the reason the Deque is worth having separately from a plain linked list or a plain array.

The RobinDict is implemented with Robin Hood Hashing, and the SwissDict is inspired from SwissTables. Both are open-addressing hash tables with different trade-offs around probing and resizing, and the documentation links the original Robin Hood hashing paper and the SwissTables write-up. The two hash table designs sitting side by side in the same package is the clearest signal that the authors expect you to benchmark rather than assume.

Then there are the structures defined by what they store rather than how they work. IntSet is a set of integers, SparseIntSet is the sparse version of the same idea, and DiBitVector packs two bits per element.

And the three trees at the end are the three classic self-balancing binary search tree designs, offered as three alternatives.

For a reader, this is the useful part of the list. The names are not arbitrary: the package names the technique where the technique is the point, which means you can look up the one entry that matches the algorithm you already understand and skip the rest.

## Mutable and immutable twins, and why the choice matters

The pairing pattern runs through the whole list and deserves a closer look, because it is the decision you will make most often.

Binary Heap sits next to Mutable Binary Heap. Linked List sits next to Mutable Linked List. Ordered Dicts and Sets are separate from the plain Sorted Dict, Sorted Multi-Dict and Sorted Set. Priority Queue and Deque each appear once, but the pattern is unmistakable elsewhere.

The distinction is the standard one in Julia. A fixed structure cannot be changed after construction, which lets the compiler specialise on the concrete type and often lets it do more work. A mutable one can be updated in place, which is what you need when the collection is long-lived and its contents change.

Because the pairs are separate names rather than a type parameter, choosing wrong is a compile-time decision rather than a runtime one. If you take a `BinaryHeap` and later need to push onto it, you are not calling a mutating method, you are replacing the type. The names force you to think about the lifetime of your data at the point where you choose the container, which is annoying in the small cases and helpful in the large ones.

`DataStructures.IntSet` and `SparseIntSet` follow a related pattern for integer keys, and the two are listed separately rather than as one configurable type, so the choice between a dense and a sparse representation is explicit.

## The repository is a package with benchmarks, docs and a test suite

The top-level entries describe a package rather than a script collection. There is a Project.toml, which is the Julia package manifest, a src/ directory for the implementation, a test/ directory for the suite, a docs/ directory, a benchmark/ directory, a CHANGELOG.md and a License.md, alongside the standard .github/ and .codecov.yml.

The presence of a benchmark/ directory is the most useful signal about how the library treats the choices above. When a package ships three hash table designs and three balanced trees, the intended way to choose is to measure, and the benchmarks are there so that you can. The project also links to a benchmark directory in the reference it points to, which is the same practice applied elsewhere in the ecosystem.

Usage details are in the documentation rather than the README, which points at the stable build and the dev build. The documentation is published in two versions. There is a stable documentation build and a dev documentation build, both hosted on the same GitHub Pages site, and the homepage for the repository is the dev build. The two-badge arrangement is a Julia convention: stable is the released version, dev tracks the master branch.

Coverage is tracked on both Coveralls and Codecov, and the CI badge points at the workflow in the repository. The ColPrac badge, for the Contributor's Guide on Collaborative Practices for Community Packages, signals that the package follows the shared community guide for Julia packages rather than a project-specific one, which means contribution expectations, code review practice and versioning conventions are documented somewhere other than this repository.

## Where it sits against the Julia standard library and the ecosystem

The comparison worth making is with the containers Julia already ships, because that is the decision you face first.

Julia's standard library has a `Dict` and a `Set` that are implemented in C and are fast. It has arrays. It does not have a priority queue, a deque, a Fenwick tree, a trie, or any of the balanced tree implementations, and it does not have the mutable and immutable pairs in the shape this package provides them. So for the core dictionary and set cases, the standard library is the answer and this package is not a competitor.

The second comparison is with the other JuliaCollections packages. The organisation publishes a set of focused packages, LRUCache among them, and the CI badge in this README points at the LRUCache workflow. The pattern is the Julia package ecosystem's, where a large general package and a set of narrow ones coexist, and the choice comes down to how much you actually need.

A third comparison is with writing the structure yourself. For a Fenwick tree or a red-black tree, a careful implementation is a few hundred lines and an afternoon. The package's value is that the implementation is already tested, benchmarked against alternatives, and typed in the idiomatic way for the language, which matters more in Julia than in most languages because the type instability costs are larger.

The one thing to weigh is the trade-off the package itself implies. Twenty-four structures is a wide surface, and the mutable and immutable pairs mean you may need to switch type mid-design. Using it narrowly, pulling in one or two structures you need, keeps that surface from becoming a problem.

## Maintenance and the version line

The package is not archived and the last push was on 2026-10-09, so the code is being worked on. The release history shows a steady 0.19 line: v0.19.6 on 2026-07-17, v0.19.5 on 2026-06-01 and v0.19.4 on 2026-03-27, which is a patch release roughly every two to three months.

The 0.19 numbering is worth understanding if you are pinning. Under the ColPrac conventions that the badge points to, a package on a 0.x version line is pre-1.0, and the minor version is where breaking changes are allowed to happen. So a 0.19.x pin is a pin within a minor line that could still change incompatibly in 0.20.

For a data structures package, the practical consequence is that you should pin more tightly than you would pin an application, and you should read the CHANGELOG.md when you upgrade rather than assuming the patch releases are API compatible with each other.

The documentation badge pair is the other practical point. If you are building something that ships, the stable documentation is the one that matches the version you pinned, and the dev documentation reflects master, which can be ahead of any release. The homepage is the dev build, so the difference between the two is not academic when you are reading a doc page and then pinning a version.

## Conclusion

Adopt DataStructures.jl if you are writing Julia and reach for a container that the standard library does not ship, especially a priority queue, a deque, a Fenwick tree or one of the balanced trees. Skip it if you only need a dictionary or a set, because the built-in ones are usually faster and already type stable. Verify first which variant you want, since many structures come in both a fixed and a mutable form and picking the wrong one costs you the ability to update in place, and read the stable documentation rather than the dev build when you are pinning a version, since the package follows the SciML ColPrac contributor guide and moves with the ecosystem.

## FAQ

### What data structures does DataStructures.jl provide?

It includes Deque implemented with an unrolled linked list, CircularBuffer, CircularDeque based on a circular buffer, Stack, Queue, Priority Queue, Fenwick Tree, Accumulators and Counters for multisets and bags, Disjoint-Sets, Binary Heap and Mutable Binary Heap, Ordered Dicts and Sets, RobinDict using Robin Hood Hashing, SwissDict inspired from SwissTables, Dictionaries with Defaults, Trie, Linked List and Mutable Linked List, Sorted Dict, Sorted Multi-Dict and Sorted Set, DataStructures.IntSet, SparseIntSet, DiBitVector, and the Red Black, AVL and Splay trees.

### When should I use DataStructures.jl instead of the Julia standard library?

The standard library covers dictionaries and sets well and is usually faster for those, so the package is for the containers it does not ship: priority queues, deques, Fenwick trees, tries, balanced trees and the mutable variants of its own structures. The package also ships a benchmark/ directory, which is the intended way to choose between the alternatives it offers.

### Why does DataStructures.jl offer both fixed and mutable versions of a structure?

The list pairs Binary Heap with Mutable Binary Heap and Linked List with Mutable Linked List, because the fixed forms let the compiler specialise on the concrete type while the mutable ones can be updated in place. Since they are separate names rather than a type parameter, picking the wrong one is a decision you make at the point of choosing the container rather than something you can change later.

## Sources

- [JuliaCollections/DataStructures.jl on GitHub](https://github.com/JuliaCollections/DataStructures.jl)
- [License: MIT](https://github.com/JuliaCollections/DataStructures.jl/blob/master/LICENSE)
- [Project website](https://juliacollections.github.io/DataStructures.jl/dev/)
- [README](https://github.com/JuliaCollections/DataStructures.jl/blob/master/README.md)
- [Releases](https://github.com/JuliaCollections/DataStructures.jl/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/juliacollections-datastructures-jl
