Successor of Ktoolz.
Collection of Kotlin extension functions and utilities. This library does not have any dependency.
Katlib is available on the Maven Central. Then to import Katlib to Gradle project use:
implementation("dev.forst", "katlib", "2.2.7")
Or with Groovy DSL
implementation 'dev.forst:katlib:2.2.7'
To import Katlib to Maven project use:
<dependency>
<groupId>dev.forst</groupId>
<artifactId>katlib</artifactId>
<version>2.2.7</version>
</dependency>
Available online - katlib.forst.dev
Feel free to submit PR with your favourite extension functions and other cool utilities!
The library contains a lot of useful (as well as useless) extensions and functions that were gathered during my (and my colleges) Kotlin career. Please see tests folder for all possible functions and how to use them. Full documentation can be found here.
Please note that some functions seems like duplicates of the standard library - usually it is not like that as they provide similar
functionality on different interface. For example there's List.random
but not Iterable.random
- random on Iterable
is then implemented
in this library. Some functions are also essentially type aliases (for example equalsIgnoreCase
) for standard library as I was having hard
time finding correct name.
However, in some cases there might be duplicates, as development of this library started in 2018 and a lot of functions came to standard library in Kotlin 1.4. - so if you find some duplicates, let me know or create PR that deprecates them in the code.
Following functions are the most popular ones.
Iterable<E>.random
- returns the random element from the iterableIterable<T>.reduction
- reduce producing list allowing you to set initial value, useful for cumulative sumsIterable<List<Int>>.sumByIndexes
- sums all Lists of integers into single one by indexesIterable<List<Double>>.sumDoublesByIndexes
- same as previous but with doublesIterable<T>.mapToSet
- creates set from iterable, transforms with given functionIterable<T>.dominantValueBy
- returns the most frequently occurring value of the given functionIterable<T1>.cartesianProduct
- cartesian product between all the elements from two iterablesIterable<T?>.forEachNotNull
- performs action on each element that is not nullIterable<Iterable<T>?>.union
- creates union of all iterablesIterable<Iterable<T>?>.intersect
- creates intersect of all iterablesIterable<T?>.filterNotNullBy
- returns list with only not null results using selectorIterable<T>.singleOrEmpty
- returns single element or null if it wasn't found, throws exception if there are multiple elementsIterable<Pair<T, V>>.splitPairCollection
- returns pair of two lists with left and right valuesIterable<T>.setDifferenceBy
- returns difference between two iterablesIterable<Pair<K, V>>.assoc
- returns map from key value pairs but logs case when key is replaced by same key with different valueIterable<Triple<A, B, C>>.flattenToLists
- returns three lists constructed from triplesIterable<T>.toNavigableSet
- creates NavigableSetIterable<T>.isEmpty
- determines whether the iterable is empty or notIterable<Iterable<T>>.cartesianProduct
- cartesian product between all the elements from nested iterablesIterable<Iterable<T>>.lazyCartesianProduct
- cartesian product between all the elements from nested iterables as sequenceIterable<A>.zip(b: Iterable<B>, c: Iterable<C>, transform: (a: A, b: B, c: C) -> V)
- zip with three collections instead of twoIterable<T>.sumByFloat(selector: (T) -> Float)
- sums iterable by float selector, becausesumOf
from stdlib does not have implementation for FloatsIterable<T>.withEach(action: T.() -> Unit)
- performs the given action with each element as a receiverIterable<T>.withEachIndexed(action: T.(index: Int) -> Unit)
- performs the given action with each element as a receiver, providing sequential index with the element
Map<T, Double>.getWeightedRandom
- randomly selects item with respect to the current weight distributionMap<K, V>.mergeReduce
- two maps together using the given reduce functionMap<K, V1>.join
- joins two maps together using the given join functionMap<K1, Map<K2, V>>.swapKeys(): Map<K2, Map<K1, V>>
- swaps keys in two-dimensional maps- there are multiple
swapKeys
implementations for up to three-dimensional maps, just browse the code Map<Pair<K1, K2>, V>.toTwoLevelMap(): Map<K1, Map<K2, V>>
- creates two-dimensional map from the map of pairsMap<Triple<K1, K2, K3>, V>.toThreeLevelMap(): Map<K1, Map<K2, Map<K3, V>>>
- creates three-dimensional map from the map of triplesMap<K1, Map<K2, V>>.getSecondLevelValues(): Set<V>
- collects all the values from the bottom level into setMap<K1, Map<K2, Map<K3, V>>>.getThirdLevelValues(): Set<V>
- collects all the values from the bottom level into setIterable<Map<K, V>>.merge(): Map<K, List<V>>
- for each key, merges all the values into one common list
SortedSet.min
- returns minimum of the set or null if emptySortedSet.max
- returns maximum of the set or null
mapLeft/Right/Pair
- applies given block to left/right/all iterable element/s of the pair
val pair = Pair(listOf(1, 2, 3), 0)
assertEquals(Pair(listOf(11, 12, 13), 0), pair.mapLeft { it + 10 })
letLeft/Right/Pair
- applies given block to left/right/all element/s of the pair
val pair = Pair(10, 20)
assertEquals(Pair("10", 20), pair.letLeft { it.toString() })
getDateRangeTo
- returns list of dates between twoLocalDate
getDaysInInterval
- returns number of days between twoLocalDate
(inclusive)getDayDifference
- returns number of days between twoLocalDate
(exclusive)getWeekOfYear
- returns week of year for givenLocalDate
and optionalyLocale
To use these, one must include dependency on Jackson
implementation("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
implementation("com.fasterxml.jackson.module", "jackson-module-kotlin", jacksonVersion)
jacksonMapper
- creates jackson mapper with some reasonable settingsparseJson
- parses JSON from the string/bytes, returns either instance of null, can log exception if some occurs
val obj: MyDataClass? = parseJson<MyDataClass>(myJson)
createJson
- creates JSON from given objectcreatePrettyJson
- creates JSON with pretty printcreateJsonBytes
- creates JSON in bytes from given objectprettyPrintJson
- returns pretty printed JSON value as string
whenTrue
and whenFalse
- useful extensions mainly used for logging when the oneliners are used.
fun someFunctionIndicatingSuccess(): Boolean =
someComputationReturningBoolean()
.whenFalse {
logger.warning { "someComputationReturningBoolean returned false! Computation probably failed" }
}
startsWithLetter
- returns true fi string starts with latin letter a-z or A-ZrestrictLengthWithEllipsis
- shortens the string to given max length, appends ellipsis
assertEquals("ABCD…", "ABCDEFHG".restrictLengthWithEllipsis(5, "..."))
toUuid
- converts string to UUID
durationToInMilli
- returns absolute difference between twoInstant
values in milliseconds
hashWithSha256
- producesSHA-256
of given string/file/bytescomputeMd5
- computes MD5 from given byte array, returns base64 encoded data
Optional<T>.orNull(): T?
- from optional to Kotlin optionalT.whenNull
- executes block whenthis
is null, useful for logging
fun someFunction(): String? =
produceOptionalString()
.whenNull { logger.warn { "produceOptionalString returned null value!" } }
T.asList
- from `this creates one element listClosedRange<T>.intersects
- intersection between rangesT.with
- bundles two objects to listvalidate
- executes invalid block if validating block returns false, useful for validation
validate(
{ someText.startsWith("something") && someText.endsWith("else") },
{ throw IllegalStateException() }
)
Pair<A?, B?>.propagateNull(): Pair<A, B>?
- if left or right is null, returns null, otherwise pairT.applyIf
- applies given block only if should apply block returns true
byteBuffer.applyIf(shouldReadInt) { getInt() }
isUuid
- returns true if given string is UUIDisUrl
- returns true if give string is URL (with some limitations, see docs)getEnv
- shortcut forSystem.getenv
newLine
- shortcut forSystem.lineSeparator
ByteArray.toUuid
- Read ByteArray as two longs and combine the to UUID
TemporalProvider
- Interface providing access to current time vianow
method, very useful when mocking
buildArray(builderAction: MutableList<E>.() -> Unit): Array<E>
- builds a new Array by populating a MutableList using the given builderAction and returning an Array with the same elementsArray<out T>.map(transform: (T) -> R): Array<R>
- Returns an array containing the results of applying the given transform function to each element in the original arrayArray<out T>.mapIndexed(transform: (index: Int, T) -> R): Array<R>
- returns an array containing the results of applying the given transform function to each element and its index in the original arrayArray<out T>.filter(predicate: (T) -> Boolean): Array<T>
- returns an array containing only elements matching the given predicateArray<out T>.filterNot(predicate: (T) -> Boolean): Array<T>
- returns an array containing all elements not matching the given predicateArray<out T>.filterIndexed(predicate: (index: Int, T) -> Boolean): Array<T>
- returns an array containing only elements matching the given predicateArray<*>.filterIsInstance(): Array<R>
- returns an array containing all elements that are instances of specified type parameter RArray<out T?>.filterNotNull(): Array<T>
- returns an array containing all elements that are notnull
Array<out T>.minus(element: T): Array<T>
- returns an array containing all elements of the original collection without the first occurrence of the given elementArray<out T>.minus(elements: Array<out T>): Array<T>
- returns an array containing all elements of the original collection except the elements contained in the given elements array
prompt(promptText: String, exceptionHandler: (e: Exception) -> String? = { null }, transform: (input: String) -> R): R
- prompts user and applies transform to input, invokes exceptionHandler if transform threw an Exception, and repeats prompt