Getting Started with Eclipse Collections — Part 1
Every journey has a beginning. This one has code and diagrams.
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.
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.
- Part 1 (This post!)— Creating Collections and Primitive Collections
- Part 2 — Adding to and removing from Collections
- Part 3 — Converting between Collection types
- Part 4 — Processing information in Collections
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
).
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 extendCollection
, 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 aCollection
type (List
,Set
,Bag
,SortedSet
,SortedBag
) - Interval — An inclusive range of
Integer
values.Interval
implementsjava.util.List<Integer>
andLazyIterable<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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
.
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);
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.
- List
- Set
- Stack
- Bag
- Primitive/Primitive Map
- Object/Primitive Map
- Primitive/Object Map
- String Adapter
- Interval
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.
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.
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);
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);
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);
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);
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);
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");
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', '!');
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);
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.