Getting Started with Eclipse Collections — Part 1

Donald Raab
15 min readFeb 21, 2023

--

Every journey has a beginning. This one has code and diagrams.

A snapshot of an example pom.xml that includes Eclipse Collections 11.1.0

Finding Eclipse Collections at Maven Central

The Eclipse Collections project has been hosted at the Eclipse Foundation for over seven years. The library has two primary jars, and a couple of supplemental jars, that can be included in your project’s build files and downloaded from Maven Central.

The README.md for Eclipse Collections includes the coordinates for Maven, Gradle, and also an OSGi bundle.

Build coordinates from Eclipse Collections README.md

The eclipse-collections-api jar is for the Eclipse Collections API, which primarily contains interfaces. The eclipse-collections jar contains all of the implementation classes.

To learn more about the two jars required for using Eclipse Collections, you can read the following blog.

Getting started with Eclipse Collections

Eclipse Collections is a comprehensive collections library for Java. There are a lot of interfaces and classes in the library, which can make it challenging to know where and how to start learning.

There are a few basic things you will want to learn in order to get started with Eclipse Collections, after you have included it in your project. The following blog posts will cover topics that will help speed you on your journey.

As you explore the library, you will learn how you can make your code more expressive and performant. The blogs in this getting started series will be as comprehensive as possible for each topic covered. I recommend reading the following blog if you would like to visualize how and why “Eclipse Collections is a comprehensive collections library for Java.”

If you prefer a hands-on approach to learning, then I would recommend completing some of the Eclipse Collections Code Katas. Many folks learn best by doing, and that is where the EC Code Katas can help.

Creating Collections

The first thing you will want to learn in Eclipse Collections is how to create instances of various Collection types. Eclipse Collections has support for Mutable and Immutable types. Eclipse Collections also has support for both object collections and primitive collections. The primitive collections provide support for all eight Java primitive types (boolean, byte, char, short, int, float, long, double).

There are three ways to create collections in Eclipse Collections.

  • Use a Constructor (e.g. new FastList())
  • Use a Static Factory Method (e.g. FastList.newList())
  • Use a Factory Class (e.g. Lists.mutable.empty())

The most convenient way to create collection containers in Eclipse Collections is to use the Factory classes. The constructor and static factory method approaches work fine, but require knowledge of the specific implementation class names you want to create. The only way to consistently create both Mutable and Immutable containers without having to learn and remember a lot of extra class names is using the Factory class approach.

Creating Containers using Factory Classes

In the following sections, there are examples of creating both Mutable and Immutable container types using Factory Classes in Eclipse Collections. Equivalent factory classes exist in both the eclipse-collections and eclipse-collections-api jars. The factory class duplication exists so default methods in the api jar can create instances of various collection types, without having to have direct references to the implementation classes. The factory classes from either jar work just as well.

The factory class names are Lists, Sets, Stacks, Bags, SortedSets, SortedBags, Maps, BiMaps, and Multimaps. If you know the collection type you want to create, just pluralize the collection type name to find the corresponding Factory class name (e.g. List -> Lists, Set -> Sets, Map -> Maps).

The Eclipse Collections Factory Classes

Object Collection Types

The following are the generic Object Collection types supported by Eclipse Collections. All object collections extend java.lang.Iterable, so they work with lJava’s forEach loop (since Java 5). All MutableCollection types extend java.util.Collection. ImmutableCollection interfaces do not extend java.util.Collection, and thus provide contractual immutability (no mutating methods). Links below take you to different sections on how to create each Collection type.

  • List — Ordered Collections that allow duplicates. Memory efficient and good for fast iteration and indexed lookup.
  • Set — Unordered Collection that does not allow duplicates. Good for uniquing and fast contains check.
  • Stack — A “last in, first out” (LIFO) data structure. Stack does not extend Collection, and has its own methods for growing (push) and shrinking (pop).
  • Bag—Unordered Collection that allow duplicates. Good for counting and for content equality test without requiring order.
  • SortedSet — A sorted Collection that does not allow duplicates. Good for keeping data sorted and unique.
  • SortedBag — A sorted Collection that allows duplicates. Good for keeping data sorted and for counting.
  • Map — A Collection of key/value pairs. Fast lookup of values by key.
  • SortedMap — A sorted Collection of key/value pairs. Fast lookup of values by key.
  • BiMap — A bi-directional Map.
  • MultiMap — A Map whose values are stored in a Collection type (List, Set, Bag, SortedSet, SortedBag)
  • Interval — An inclusive range of Integer values. Interval implements java.util.List<Integer> and LazyIterable<Integer>.

Creating Lists

The following code examples show how to use the Lists factory class to create MutableList and ImmutableList instances.

// Empty MutableList
MutableList<String> emptyList =
Lists.mutable.empty();

// MutableList with three elements
MutableList<String> list =
Lists.mutable.with("1", "2", "3");

// Empty ImmutableList
ImmutableList<String> emptyImmutableList =
Lists.immutable.empty();

// ImmutableList with three elements
ImmutableList<String> immutableList =
Lists.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableList and ImmutableList, and how the Lists factory class can be used to create either type.

Lists Factory class with relationships

The following sequence diagram shows the messages sent to the Lists class as well as the corresponding MutableListFactory and ImmutableListFactory types. This visualizes how the code example above works.

Sequence Diagram for Lists factory examples

Return to TOC

Creating Sets

The following code examples show how to use the Sets factory class to create MutableSet and ImmutableSet instances.

// Empty MutableSet
MutableSet<String> emptySet =
Sets.mutable.empty();

// MutableSet with three elements
MutableSet<String> set =
Sets.mutable.with("1", "2", "3");

// Empty ImmutableSet
ImmutableSet<String> emptyImmutableSet =
Sets.immutable.empty();

// ImmutableSet with three elements
ImmutableSet<String> immutableSet =
Sets.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableSet and ImmutableSet, and how the Sets factory class can be used to create either type.

Sets Factory class with relationships

Return to TOC

Creating Stacks

The following code examples show how to use the Stacks factory class to create MutableStack and ImmutableStack instances.

// Empty MutableStack
MutableStack<String> emptyStack =
Stacks.mutable.empty();

// MutableStack with three elements
MutableStack<String> stack =
Stacks.mutable.with("1", "2", "3");

// Empty MutableStack
ImmutableStack<String> emptyImmutableStack =
Stacks.immutable.empty();

// ImmutableStack with three elements
ImmutableStack<String> immutableStack =
Stacks.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableStack and ImmutableStack, and how the Stacks factory class can be used to create either type. Noe, the Stack interfaces in Eclipse Collections are not related to the java.util.Stack class. There is no Stack interface in the JDK. MutableStack does not extend MutableCollection, as a MutableStack has a different mutable API (push, pop) than MutableCollection (add, remove). I will cover add, remove, push and pop in the next blog in this series.

Stacks Factory class with relationships

Return to TOC

Creating Bags

The following code examples show how to use the Bags factory class to create MutableBag and ImmutableBag instances.

// Empty MutableBag
MutableBag<String> emptyBag =
Bags.mutable.empty();

// MutableBag with three elements
MutableBag<String> bag =
Bags.mutable.with("1", "2", "3");

// Empty ImmutableBag
ImmutableBag<String> emptyImmutableBag =
Bags.immutable.empty();

// ImmutableBag with three elements
ImmutableBag<String> immutableBag =
Bags.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableBag and ImmutableBag, and how the Bags factory class can be used to create either type.

Bags Factory class with relationships

Return to TOC

Creating SortedSets

The following code examples show how to use the SortedSets class to create MutableSortedSet and ImmutableSortedSet instances.

// Empty MutableSortedSet
MutableSortedSet<String> emptySortedSet =
SortedSets.mutable.empty();

// MutableSortedSet with three elements
MutableSortedSet<String> sortedSet =
SortedSets.mutable.with("1", "2", "3");

// Empty ImmutableSortedSet
ImmutableSortedSet<String> emptyImmutableSortedSet =
SortedSets.immutable.empty();

// MutableSortedSet with three elements
ImmutableSortedSet<String> immutableSortedSet =
SortedSets.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableSortedSet and ImmutableSortedSet, and how the SortedSets factory class can be used to create either type.

SortedSets Factory class with relationships

Return to TOC

Creating SortedBags

The following code examples show how to use the SortedBags factory class to create MutableSortedBag and ImmutableSortedBag instances.

// Empty MutableSortedBag
MutableSortedBag<String> emptySortedBag =
SortedBags.mutable.empty();

// MutableSortedBag with three elements
MutableSortedBag<String> sortedBag =
SortedBags.mutable.with("1", "2", "3");

// Empty ImmutableSortedBag
ImmutableSortedBag<String> emptyImmutableSortedBag =
SortedBags.immutable.empty();

// ImmutableSortedBag with three elements
ImmutableSortedBag<String> immutableSortedBag =
SortedBags.immutable.with("1", "2", "3");

The following class diagram shows the relationships between MutableSortedBag and ImmutableSortedBag, and how the SortedBags factory class can be used to create either type.

SortedBags Factory class with relationships

Return to TOC

Creating Maps

The following code examples show how to use the Maps factory class to create MutableMap and ImmutableMap instances.

// Empty MutableMap
MutableMap<String, String> emptyMap =
Maps.mutable.empty();

// MutableMap with three elements
MutableMap<Integer, String> map =
Maps.mutable.with(1, "1", 2, "2", 3, "3");

// Empty MutableMap
ImmutableMap<String, String> emptyImmutableMap =
Maps.immutable.empty();

// MutableMap with three elements
ImmutableMap<Integer, String> immutableMap =
Maps.immutable.with(1, "1", 2, "2", 3, "3");

The following class diagram shows the relationships between MutableMap and ImmutableMap, and how the Maps factory class can be used to create either type.

Maps Factory class with relationships

Return to TOC

Creating SortedMaps

The following code examples show how to use the SortedMaps factory class to create MutableSortedMap and ImmutableSortedMap instances.

// Empty MutableSortedMap
MutableSortedMap<String, String> emptySortedMap =
SortedMaps.mutable.empty();

// MutableSortedMap with three elements
MutableSortedMap<Integer, String> sortedMap =
SortedMaps.mutable.with(1, "1", 2, "2", 3, "3");

// Empty MutableSortedMap
ImmutableSortedMap<String, String> emptyImmutableSortedMap =
SortedMaps.immutable.empty();

// MutableSortedMap with three elements
ImmutableSortedMap<Integer, String> immutableSortedMap =
SortedMaps.immutable.with(1, "1", 2, "2", 3, "3");

The following class diagram shows the relationships between MutableSortedMap and ImmutableSortedMap, and how the SortedMaps factory class can be used to create either type.

SortedMaps Factory class with relationships

Return to TOC

Creating BiMaps

The following code examples show how to use the BiMaps factory class to create MutableBiMap and ImmutableBiMap instances. The examples also show how to invert a BiMap using the inverse method.

// Empty MutableMap
MutableBiMap<Integer, String> emptyBiMap =
BiMaps.mutable.empty();

// Inverting the MutableMap
MutableBiMap<String, Integer> emptyInverse =
emptyBiMap.inverse();

// MutableMap with three elements
MutableBiMap<Integer, String> biMap =
BiMaps.mutable.with(1, "1", 2, "2", 3, "3");

// Inverting the MutableMap
MutableBiMap<String, Integer> biMapInverse =
biMap.inverse();

// Empty MutableMap
ImmutableBiMap<Integer, String> emptyImmutableBiMap =
BiMaps.immutable.empty();

// Inverting the ImmutableBiMap
ImmutableBiMap<String, Integer> emptyImmutableBiMapInverse =
emptyImmutableBiMap.inverse();

// MutableMap with three elements
ImmutableBiMap<Integer, String> immutableBiMap =
BiMaps.immutable.with(1, "1", 2, "2", 3, "3");

// Inverting the ImmutableBiMap
ImmutableBiMap<String, Integer> immutableBiMapInverse =
immutableBiMap.inverse();

The following class diagram shows the relationships between MutableBiMap and ImmutableBiMap, and how the BiMaps factory class can be used to create either type.

BiMaps Factory class with relationships

Return to TOC

Creating Multimaps

The following code examples show how to use the Multimaps factory class to create MutableMultimap and ImmutableMultimap instances. There are List, Set, Bag, SortedSet, and SortedBag variations of Multimap. Each Multimap type has Mutable and Immutable variations.

// Empty MutableListMultimap
MutableListMultimap<String, String> listMultimap =
Multimaps.mutable.list.empty();

// Empty MutableSetMultimap
MutableSetMultimap<String, String> setMultimap =
Multimaps.mutable.set.empty();

// Empty MutableBagMultimap
MutableBagMultimap<String, String> bagMultimap =
Multimaps.mutable.bag.empty();

// Empty MutableSortedSetMultimap
MutableSortedSetMultimap<String, String> sortedSetMultimap =
Multimaps.mutable.sortedSet.with(Comparator.<String>naturalOrder());

// Empty MutableSortedBagMultimap
MutableSortedBagMultimap<String, String> sortedBagMultimap =
Multimaps.mutable.sortedBag.with(Comparator.<String>naturalOrder());

// Empty ImmutableListMultimap
ImmutableListMultimap<String, String> immutableListMultimap =
Multimaps.immutable.list.empty();

// Empty ImmutableSetMultimap
ImmutableSetMultimap<String, String> immutableSetMultimap =
Multimaps.immutable.set.empty();

// Empty ImmutableBagMultimap
ImmutableBagMultimap<String, String> immutableBagMultimap =
Multimaps.immutable.bag.empty();

// Empty ImmutableSortedSetMultimap
ImmutableSortedSetMultimap<String, String> immutableSortedSetMultimap =
Multimaps.immutable.sortedSet.with(Comparator.<String>naturalOrder());

// Empty ImmutableSortedBagMultimap
ImmutableSortedBagMultimap<String, String> immutableSortedBagMultimap =
Multimaps.immutable.sortedBag.with(Comparator.<String>naturalOrder());

The following class diagram shows the relationships between MutableMultimaps and ImmutableMultimaps, and how the Multimaps factory class can be used to create the different variations of Multimap.

Return to TOC

Creating Intervals

The Interval class is an inclusive range of Integer that implements List<Integer>. Interval is Immutable. Interval will throw an UnsupportedOperationException for any mutating methods it implements from the List API. An Interval has a from and to value that are inclusive, and a step value. The Interval class in Eclipse Collections does not have a separate factory class. It also does not have a separate interface, so only exists in the implementation jar.

// One element Interval
Interval one = Interval.fromToBy(1, 1, 1);

// One to Ten
Interval oneToTen = Interval.oneTo(10);

// Zero to Nine
Interval zeroToNine = Interval.zeroTo(9);

// Evens from 1 to 100
Interval evens = Interval.evensFromTo(1, 100);

// Odds from 1 to 100
Interval odds = Interval.oddsFromTo(1, 100);

// 1 to 20 by 5
Interval oneToTwentybyFive = Interval.fromToBy(1, 100, 5);

// 0 to -100
Interval negativeRange = Interval.zeroTo(-100);

Return to TOC

Creating other lesser known Collections

The following blogs explain more about the missing Java data structures that no one ever told you about. There is an explanation how to create HashingStrategy Collections/Maps, and MultiReader Collections.

Creating Primitive Collections

Eclipse Collections provides primitive collections support for all eight primitive types (boolean, byte, char, short, int, float, long, double). There are Mutable and Immutable forms of all primitive container types.

The convention used for the naming of primitive collection factory classes is simple. The prefix is the primitive type (Boolean, Byte, Char, Short, Int, Float, Long, Double) followed by the container type pluralized (Lists, Sets, Bags, Stacks, Maps). Some primitive factory class examples are DoubleLists, ShortSets, FloatBags, IntStacks, ObjectIntMaps, IntObjectMaps, and CharLongMaps.

Primitive Collection Types

The follow are the primitive Collection types supported by Eclipse Collections.

Creating Primitive Lists

The following code examples show how to use the DoubleLists factory class to create MutableDoubleList and ImmutableDoubleList instances. Equivalent primitive List factories exists for all eight primitive types.

// Empty MutableDoubleList
MutableDoubleList emptyList =
DoubleLists.mutable.empty();

// MutableDoubleList with three elements
MutableDoubleList list =
DoubleLists.mutable.with(1.0, 2.0, 3.0);

// Empty ImmutableDoubleList
ImmutableDoubleList emptyImmutableList =
DoubleLists.immutable.empty();

// ImmutableDoubleList with three elements
ImmutableDoubleList immutableList =
DoubleLists.immutable.with(1.0, 2.0, 3.0);

The following class diagram shows the relationships between MutableDoubleList and ImmutableDoubleList, and how the DoubleLists factory class can be used to create either type. Other primitive collection factory class diagrams will look very similar to this one, so I will not include additional ones.

DoubleLists Factory class with relationships

The following sequence diagram shows the messages sent to the DoubleLists class as well as the corresponding MutableDoubleListFactory and ImmutableDoubleListFactory types. This visualizes how the code example above works.

Sequence Diagram for DoubleLists factory examples

Return to TOC

Creating Primitive Sets

The following code examples show how to use the ShortSets factory class to create MutableShortSet and ImmutableShortSet instances. Equivalent primitive Set factories exists for all eight primitive types.

// Empty MutableShortSet
MutableShortSet emptySet =
ShortSets.mutable.empty();

// MutableShortSet with three elements
MutableShortSet set =
ShortSets.mutable.with((short) 1, (short) 2, (short) 3);

// Empty ImmutableShortSet
ImmutableShortSet emptyImmutableSet =
ShortSets.immutable.empty();

// ImmutableShortSet with three elements
ImmutableShortSet immutableSet =
ShortSets.immutable.with((short) 1, (short) 2, (short) 3);

Return to TOC

Creating Primitive Stacks

The following code examples show how to use the IntStacks factory class to create MutableIntStack and ImmutableIntStack instances. Equivalent primitive Stack factories exists for all eight primitive types.

// Empty MutableIntStack
MutableIntStack emptyStack =
IntStacks.mutable.empty();

// MutableIntStack with three elements
MutableIntStack stack =
IntStacks.mutable.with(1, 2, 3);

// Empty ImmutableIntStack
ImmutableIntStack emptyImmutableStack =
IntStacks.immutable.empty();

// ImmutableIntStack with three elements
ImmutableIntStack immutableStack =
IntStacks.immutable.with(1, 2, 3);

Return to TOC

Creating Primitive Bags

The following code examples show how to use the FloatBags factory class to create MutableFloatBag and ImmutableFloatBag instances. Equivalent primitive Bag factories exists for all eight primitive types.

// Empty MutableFloatBag
MutableFloatBag emptyBag =
FloatBags.mutable.empty();

// MutableFloatBag with three elements
MutableFloatBag bag =
FloatBags.mutable.with(1.0f, 2.0f, 3.0f);

// Empty ImmutableFloatBag
ImmutableFloatBag emptyImmutableBag =
FloatBags.immutable.empty();

// ImmutableFloatBag with three elements
ImmutableFloatBag immutableBag =
FloatBags.immutable.with(1.0f, 2.0f, 3.0f);

Return to TOC

Creating Primitive/Primitive Maps

The following code examples show how to use the CharLongMaps factory class to create MutableCharLongMap and ImmutableCharLongMap instances. Equivalent primitive/primitive Map factories exists for all combinations of primitive/primitive types.

// Empty MutableCharLongMap
MutableCharLongMap emptyMap =
CharLongMaps.mutable.empty();

// MutableCharLongMap with three elements
MutableCharLongMap map =
CharLongMaps.mutable.with('1', 1L, '2', 2L, '3', 3L);

// Empty ImmutableCharLongMap
ImmutableCharLongMap emptyImmutableMap =
CharLongMaps.immutable.empty();

// ImmutableCharLongMap with three elements
ImmutableCharLongMap immutableMap =
CharLongMaps.immutable.with('1', 1L, '2', 2L, '3', 3L);

Return to TOC

Creating Object/Primitive Maps

The following code examples show how to use the ObjectIntMaps factory class to create MutableObjectIntMap and ImmutableObjectIntMap instances. Equivalent object/primitive Map factories exists for all eight primitive types.

// Empty MutableObjectIntMap
MutableObjectIntMap<String> emptyMap =
ObjectIntMaps.mutable.empty();

// MutableObjectIntMap with three elements
MutableObjectIntMap<String> map =
ObjectIntMaps.mutable.with("1", 1, "2", 2, "3", 3);

// Empty ImmutableObjectIntMap
ImmutableObjectIntMap<String> emptyImmutableMap =
ObjectIntMaps.immutable.empty();

// ImmutableObjectIntMap with one element
ImmutableObjectIntMap<String> immutableMap =
ObjectIntMaps.immutable.with("1", 1);

Return to TOC

Creating Primitive/Object Maps

The following code examples show how to use the IntObjectMaps factory class to create MutableIntObjectMap and ImmutableIntObjectMap instances. Equivalent primitive/object Map factories exists for all eight primitive types.

// Empty MutableIntObjectMap
MutableIntObjectMap<String> emptyMap =
IntObjectMaps.mutable.empty();

// MutableIntObjectMap with three elements
MutableIntObjectMap<String> map =
IntObjectMaps.mutable.with(1, "1", 2, "2", 3, "3");

// Empty ImmutableObjectIntMap
ImmutableIntObjectMap<String> emptyImmutableMap =
IntObjectMaps.immutable.empty();

// ImmutableObjectIntMap with one element
ImmutableIntObjectMap<String> immutableMap =
IntObjectMaps.immutable.with(1, "1");

Return to TOC

Creating String Adapters

There are three String adapter classes in Eclipse Collections. The classes are CharAdapter, CodePointAdapter and CodePointList. These classes can be instantiated via static factory methods on the classes directly, or by using the Strings factory class.

// Hello World! as a CharAdapter
CharAdapter charAdapter =
Strings.asChars("Hello World!");

// Hello World! as a CodePointAdapter
CodePointAdapter codePointAdapter =
Strings.asCodePoints("Hello World!");

// Hello World! from code point values
CodePointAdapter fromCodePoints =
Strings.toCodePoints(72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33);

// Hello World! from char values
CharAdapter fromChars =
Strings.toChars('H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!');

Return to TOC

Creating Primitive Intervals

There are two primitive Interval types. They are IntInterval and LongIterval. Unlike the Interval object collection which implements List<Integer> and LazyIterable<Integer>, IntInterval implements ImmutableIntList and LongIterval implements ImmutableLongList.

// One element IntInterval
IntInterval one = IntInterval.fromToBy(1, 1, 1);

// One to Ten LongInterval
LongInterval oneToTen = LongInterval.oneTo(10L);

// Zero to Nine IntInterval
IntInterval zeroToNine = IntInterval.zeroTo(9);

// Evens from 1 to 100 LongInterval
LongInterval evens = LongInterval.evensFromTo(1L, 100L);

// Odds from 1 to 100 IntInterval
IntInterval odds = IntInterval.oddsFromTo(1, 100);

// 1 to 20 by 5 LongInterval
LongInterval oneToTwentybyFive = LongInterval.fromToBy(1L, 100L, 5L);

// 0 to -100 IntInterval
IntInterval negativeRange = IntInterval.zeroTo(-100);

Return to TOC

More about primitive Collections

This blog focused primarily on how to create primitive collections. The following blog goes into more detail on leveraging primitive collections, and the benefits.

More Factory Examples

For additional examples of creating Mutable and Immtuable collections, please read the following blogs.

Final Thoughts

Thank you for taking the time to read this blog. I hope this will be a good reference for folks to refer to in the future. I tried to be as comprehensive as possible. In the next blog in this series, I will cover in depth how to add and remove items from different collection types.

Enjoy!

I am the creator of and a Committer for the Eclipse Collections OSS project which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.

--

--

Donald Raab

Java Champion. Creator of the Eclipse Collections OSS Java library (https://github.com/eclipse/eclipse-collections). Inspired by Smalltalk. Opinions are my own.