Utilities and extension function for custom LibGDX collections.
For better and for worse, LibGDX collections do not implement interfaces or extend any abstract classes from the legendary
java.util package. Although standard Kotlin library features superb utilities, some of them be used along with the
LibGDX collections simply because they do not implement the Collection interface. Not to mention LibGDX collections
could use some extensions and factory methods, as well as fully benefit from the syntax sugar (like square brackets
operators) that Kotlin comes with.
LibGDX features unfortunate Array class, which works similarly to ArrayList, but it reuses its iterators. Its name
clashes with kotlin.Array, so it is advised to import it with import com.badlogic.gdx.utils.Array as GdxArray when
necessary.
Arrayinstances can be constructed withgdxArrayOfmethods, similarly to how you create native arrays in Kotlin.- Null-safe
isEmpty(),isNotEmpty()andsize()methods where added. They allow you to inspect the collection even if the variable is a possible null. - Null-safe inlined extension property
lastIndexwas added. It returns index of last element in the list - or-1if the list is null or empty. +and-operators were overridden: they allow to add or remove elements from the collection. They can be invoked with a compatible element type or another collection storing values of the same type. Both operator invocations can be chained. These operators return a new collection with specified added or removed elements.+=and-=operators were overridden: they allow to add or remove elements from an existing collection, modifying its content.getLastandremoveLastutility extension methods were added.- Utility
sortDescending,sortByandsortByDescendingextension methods were added to ease list sorting. - Get-or-else extension method was added and is available through
array[index, alternative]syntax. - Missing
addAllandremoveAllmethods for arrays and iterables were added. iteratemethod allows to iterate over collection's elements, while providing reference toMutableInterator. Can be used to easily remove collection elements during iteration.removeAllandretainAllhigher-order functions that work like collection extensions in Kotlin stdlib. APoolcan optionally be passed to automatically free the removed items.transferextension method can be used to move elements from one array to another using a lambda predicate.map,filter,flattenandflatMapmethods that work like methods in Kotlin stdlib but returnGdxArray.- Every iterable and array can be converted to
ArrayusingtoGdxArraymethod. IntArray,BooleanArrayandFloatArraycan be converted to corresponding LibGDX primitive collections usingtoGdxArraymethod.- Type aliases added for LibGDX collections to avoid collisions with the standard library:
GdxArray:com.badlogic.gdx.utils.ArrayGdxIntArray:com.badlogic.gdx.utils.IntArrayGdxFloatArray:com.badlogic.gdx.utils.FloatArrayGdxBooleanArray:com.badlogic.gdx.utils.BooleanArrayGdxCharArray:com.badlogic.gdx.utils.CharArrayGdxLongArray:com.badlogic.gdx.utils.LongArrayGdxShortArray:com.badlogic.gdx.utils.ShortArray
LibGDX features ObjectSet class, which works similarly to HashSet, but it reuses its iterators.
ObjectSetinstances can be constructed withgdxSetOfmethods, similarly to how you create native arrays in Kotlin.- Null-safe
isEmpty(),isNotEmpty()andsize()methods where added. They allow you to inspect the collection even if the variable is a possible null. +and-operators were overridden: they allow to add or remove elements from the collection. They can be invoked with a compatible element type or another collection storing values of the same type. Both operator invocations can be chained. These operators return a new collection with specified added or removed elements.+=and-=operators were overridden: they allow to add or remove elements from an existing collection, modifying its content.- Missing
addAllandremoveAllmethods for arrays and iterables were added. iteratemethod allows to iterate over collection's elements, while providing reference toMutableIterator. Can be used to easily remove collection elements during iteration.map,filter,flattenandflatMapmethods that work like methods in Kotlin stdlib but returnGdxSet.- Every iterable and array can be converted to
ObjectSetusingtoGdxSetmethod. IntArraycan be converted toIntSetusingtoGdxSetmethod.- Type alias added for consistency with other collections:
GdxSet-com.badlogic.gdx.utils.ObjectSet.
LibGDX features ObjectMap class, which works similarly to HashMap, but it reuses its iterators.
ObjectMapinstances can be constructed withgdxMapOfmethods, similarly to how you createjava.utilmaps in Kotlin.IdentityMapinstances can be constructed withgdxIdentityMapOfmethods. Added some basic support for LibGDXIdentityMapand optimized primitiveIntIntMap,IntFloatMapandIntMapcollections.- Null-safe
isEmpty(),isNotEmpty()andsize()methods where added. They allow you to inspect the collection even if the variable is a possible null. inoperator can be used to check if a particular key is stored in the map.- Square bracket syntax can be used to add new elements to the maps:
map[key] = valueis an equivalent tomap.put(key, value). iteratemethod allows to iterate over map elements with a reference toMutableIterator. Can be used to easily remove elements from the map.map,filter,flattenandflatMapmethods that work like methods in Kotlin stdlib but returnGdxMapandGdxArray.- Keys stored in the map can be quickly converted to an
ObjectSetusingtoGdxSetmethod. - Every iterable and array can be converted to
ObjectMapusingtoGdxMapmethod. A lambda that converts values to keys has to be provided - since the method is inlined, no new lambda object will be created at runtime. - Type aliases were added for consistency with other collections:
GdxMap:com.badlogic.gdx.utils.ObjectMapGdxIdentityMap:com.badlogic.gdx.utils.IdentityMapGdxArrayMap:com.badlogic.gdx.utils.ArrayMap
- All LibGDX map entries now feature
component1()andcomponent2()operator extension methods, so they can be destructed into a key and a value. getOrPutforObjectMap,IdentityMap,ArrayMapandIntMapmethod to get an existing value to a given key or if it does not exist, create a default value, add it to the map and return it.
It is highly advised to use ktx.collections.* import when working with LibGDX collections. Kotlin standard library
comes with multiple unoptimized utility methods for Iterable instances - like - operator that iterates over the
whole collection to remove an element, which would be highly inefficient in case of ObjectSet, for example. By using
a wildcard import of all KTX utilities, you can make sure that you're using the correct extension method
implementations.
IntelliJ allows to mark packages for automatic wildcard import at Settings > Editor > Code Style > Kotlin > Imports.
Working with LibGDX Array:
import ktx.collections.*
val array = gdxArrayOf("zero", "one", "two")
array[0] // "zero"
"one" in array // true
array += "three" // array[3] == "three"; array.size == 4
array -= "three" // "three" in array == false; array.size == 3
array += arrayOf("three", "four") // array[3] == "three", array[4] = "four"
val empty = gdxArrayOf<String>()Working with LibGDX ObjectSet:
import ktx.collections.*
val set = gdxSetOf("zero", "one", "two")
"one" in set // true
set += "three" // "three" in set == true; set.size = 4
set -= "three" // "three" in set == false; set.size == 3
set += arrayOf("three", "four") // "three" in set == true; "four" in set == true
val empty = gdxSetOf<String>()Working with LibGDX ObjectMap:
import ktx.collections.*
val map = gdxMapOf(0 to "zero", 1 to "one", 2 to "two")
0 in map // true
map[0] // "zero"
map[3] = "three" // 3 in map == true; map[3] == "three"
val empty = gdxMapOf<Int, String>()Iterating over LibGDX maps with destructing syntax:
import ktx.collections.*
val map = gdxMapOf(0 to "zero", 1 to "one", 2 to "two")
map.forEach { (key, value) ->
println("$value was mapped to $key.")
}- Kotlin standard library provides utilities for default Java collections, although you should be aware that
java.utilcollections can cause garbage collection issues on slower devices. - LibGDX Kiwi utilities contains a module which helps with LibGDX
collections - but since it is written with Java,
ktx-collectionsis arguably easier to use in Kotlin applications. It is still worth looking into for its so-called lazy, disposable and immutable collections. - Koloboke contains efficient implementations of sets and maps that can use
unboxed primitive types as keys or values. While, (un)fortunately, its API design and implementation is most likely
significantly better than LibGDX collections (to be honest), it is also a huge dependency due to the sheer amount of
available collections. Note that Koloboke collections are compatible with
java.utilcollections API, while LibGDX collections are not - Koloboke maps and sets can fully benefit from Kotlin standard library utilities.