Framework
vigna/fastutil avatar
vigna/fastutil

fastutil: primitive collections that implement the standard interfaces

fastutil extends the Java™ Collections Framework by providing type-specific maps, sets, lists and queues.

2,250 stars233 forksJavaApache-2.0

At a glance

What is it?
fastutil gives Java engineers type-specific maps, sets, lists and queues that still implement the standard collection interfaces, so existing code can accept them. Its sources are generated from driver files, its core jar repeats classes from the full jar, and its own speed claim has to be measured in your application.
Who is it for?
Adopt fastutil when your working set is measured in primitive longs or ints and you already have a benchmark harness that can measure the win on your own data. Leave it out for a codebase that lives on boxed objects, where interface compatibility buys little and generated sources buy nothing.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • vigna/fastutil2,250 ★ · -1
Star history
Repository2026-10-142026-10-23
vigna/fastutil2.3k2.3k

-1 Stars in the last 9 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Type-specific collections behind the standard Java interfaces

A Java engineer reaches for a map of longs and gets an object wrapper per element, and that gap is what this library fills. fastutil extends the Java™ Collections Framework by providing type-specific maps, sets, lists and queues with a small memory footprint and fast access and insertion, and it adds big 64-bit arrays, sets and lists plus I/O classes for binary and text files. What matters for adoption is that each class implements its standard counterpart interface, so a field or a parameter typed as that interface accepts a fastutil implementation and existing code takes it. On top of that, the classes carry features the standard classes do not have, and the one named in the introduction is bidirectional iterators. The library is free software distributed under the Apache License 2.0, with the `LICENSE-2.0` file sitting in the repository root next to `README.md`.

Driver files and a C preprocessor generate the Java sources

The repository is not a directory of finished Java files. The sources are generated using a C preprocessor, starting from a set of driver files, and `gencsource.sh` is the script that does it: the script reads in a driver file, that is, a Java source that uses some preprocessor-defined symbols and some conditional compilation, and produces a fake C source which includes the driver code and some definitions that customize the environment. The top-level tree carries `drv/`, `src/` and that script side by side, so every class starts life as a template rather than as a separate hand-written file. That arrangement is what keeps a family of classes spanning each type and each container shape affordable to produce. For the reasoning behind it, the README sends you to the javadoc-generated documentation, where an overview explains the design choices used in fastutil, and that is where to look before you copy a class into a base class of your own.

Building from source means generating the sources first

The build has a fixed order, and generation comes first. `make sources` gets the actual Java sources, and only then do the ant tasks run:

bash
make sources
ant jar
ant javadoc
ant junit

Expect a single jar file from `ant jar`, the API documentation from `ant javadoc`, and the unit test run from `ant junit`. Neither of the two jars people usually want comes out of that first command. Getting the standard jar and the core jar means running the split script and then the OSGi packaging task:

bash
split.sh
ant osgi-rest

Inputs to that second step are the top-level entries `fastutil.bnd`, `fastutil-core.bnd` and the `bnd/` directory, so the bundle metadata lives in its own files rather than inside `build.xml`. No Java or Ant version is stated anywhere in the build notes, so pin whatever your CI already runs. The last push was on 2026-09-13 and the repository has no GitHub releases, so the `CHANGES` and `REVISION.md` entries in the tree are where to look for what moved.

The core jar duplicates classes the standard jar already carries

If the standard `fastutil` jar is too large, the offered answer is a core jar containing only data structures specific for integers, longs and doubles. Right in the very next sentence sits the catch: those classes are duplicated in the standard jar, so if you are depending on both, for example because of transitive dependencies, you should exclude the core jar. Two artifacts that look like a size optimization therefore become a classpath decision you have to make deliberately, and a build that drags the core jar in through a library you did not choose leaves the same class present twice, which is the exact situation the note tells you to avoid. Nothing in the notes says which copy wins in that case, so treat any inherited core jar as something to look for in your dependency tree. The single JDK reference in the build notes is attached to `jdeps` and JDK 8 in the shrinking script, not to either jar, so confirm the jar you pick against the JDK your build actually runs.

find-deps.sh builds a jar holding only the classes you call

A jar you build yourself is the smallest option available. The notes say you can create a small, customized fastutil jar, which you can put in your repo, local maven repo, etc., using the `find-deps.sh` shell script. Prerequisites are mild: only the `jdeps` tool is required, and `jdeps` is bundled with JDK 8. The script identifies all fastutil classes your project uses and builds a minimized jar containing only the necessary classes. For a team that ships a container image and counts every megabyte, that is the concrete answer to the standard jar being too large. In exchange, the artifact is yours rather than the published one, so its contents follow your own code paths and need rebuilding whenever those paths move, and anyone reading your build has no published artifact to compare it against.

Big collections pass 2^31 through arrays of arrays

With `fastutil` 6, a second generation of classes handles very large collections, in particular collections whose size exceeds 2^31, which is past what an int-sized index can address. Big arrays are arrays of arrays, and a wealth of static methods act on them as if they were monodimensional arrays with 64-bit indices, so callers keep writing one-dimensional code over two-dimensional storage. Big lists provide 64-bit list access. For the hash variant, the bound is given as a resource rather than a constant: the size of a hash big set is limited only by the amount of core memory. That sentence also marks where the feature stops, because nothing in the notes describes a disk-backed or spilling variant, so a collection that outgrows core memory has no documented path inside this library.

References compare with the equality operator, not equals()

Besides objects and primitive types, fastutil provides support for references, that is, objects that are compared using the equality operator rather than the equals() method. In a cache keyed by identity, or a map holding interned keys, that is the comparison you actually mean, and a standard keyed collection does not offer it, so the choice matters whenever identity is the real key. It also means one codebase can carry two different notions of duplicate depending on which class you picked, which is a decision worth writing down once. The README gives this in a single sentence with no example, so the constructors and the key semantics belong in the javadoc overview, which the README names as the place where the design choices are explained. Nothing in the notes says how references behave with the big structures or with the binary and text I/O classes.

The fastest available claim is withdrawn in the same section

In its Speed section the README states that fastutil provides in many cases the fastest implementations available, and then takes the claim back within a few lines. Two lines later the same section says authors are a little bit quick in defining their implementations the 'fastest available', because you have to take decisions in any implementation, and those decisions make it faster in one scenario and slower in another. Read in order, the two sentences cancel, which is worth knowing before a public benchmark settles your dependency list. What survives is concrete: test speed within your own application rather than relying on general benchmarks, ask the authors how to use the libraries in an optimal way, and when you test hash-based data structures, set the load factor explicitly, because speed is strongly dependent on the length of collision chains. That last point is the one most published comparisons skip, and it applies to every hash-based collection in your process, not only to this library. Two other implementations of primitive collections are named in the same section, HPPC and Koloboke, with no table to separate them. The real difference between the three is the set of internal decisions their authors made, so documentation alone cannot pick one for you. Having a measurement harness is the honest entry cost.

Editorial conclusion

Adopt fastutil when your working set is measured in primitive longs or ints and you already have a benchmark harness that can measure the win on your own data. Leave it out for a codebase that lives on boxed objects, where interface compatibility buys little and generated sources buy nothing. Before you commit, run `find-deps.sh` over a real build, exclude the core jar whenever the full jar is already on the classpath, and read the javadoc overview before assuming a class behaves exactly like its standard counterpart.

Frequently asked questions

How do I add fastutil to a Maven project?

The README badges point at Maven Central under the group `it.unimi.dsi` and at the javadoc for the artifact, but the README prints no dependency snippet, so the coordinates have to come from those links.

Does fastutil replace the Java Collections Framework?

No. Its classes implement their standard counterpart interface, so they are dropped into existing code as implementations of it, and they also add features the standard classes do not have, such as bidirectional iterators.

Can a fastutil collection hold more than 2^31 elements?

With `fastutil` 6, big arrays and big lists give 64-bit access and handle collections whose size exceeds 2^31, and the size of a hash big set is limited only by the amount of core memory.

Why does fastutil's own documentation tell me to test speed myself?

Because the Speed section withdraws its own fastest available claim and notes that every implementation trades decisions across scenarios. What it keeps is test inside your own application, ask the authors about optimal use, and set the load factor explicitly when testing hash-based structures.

What does the sorting-algorithms repository topic refer to?

The README describes type-specific maps, sets, lists and queues, big arrays, sets and lists, and I/O classes for binary and text files, and it names no sorting entry point. The javadoc overview is the place it points to for design choices.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. vigna/fastutil on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vigna-fastutil.svg)](https://hysenlabs.com/projects/vigna-fastutil)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/vigna-fastutil.svg)](https://hysenlabs.com/projects/vigna-fastutil)

Was this useful?