All Downloads are FREE. Search and download functionalities are using the official Maven repository.

walkmc.extensions.collections.Maps.kt Maven / Gradle / Ivy

@file:Suppress("NOTHING_TO_INLINE")

package walkmc.extensions.collections

import net.jodah.expiringmap.*
import org.checkerframework.checker.units.qual.*
import walkmc.*
import walkmc.extensions.*
import java.util.*

typealias ExpiringMapBuilder = ExpiringMap.Builder.() -> Unit

/**
 * Creates a new enum map with the specified [entries].
 */
inline fun , V> enumMapOf(vararg entries: Pair): EnumMap {
	val result = EnumMap(T::class.java)
	result.putAll(entries)
	return result
}

/**
 * Creates a new empty enum map.
 */
inline fun , V> enumMapOf(): EnumMap = EnumMap(T::class.java)

/**
 * Creates a new empty tree map with a optional [comparator].
 */
fun  treeMapOf(comparator: Comparator? = null) = TreeMap(comparator)

/**
 * Creates a new empty tree map with a optional [comparator].
 */
fun  treeMapOf(
	vararg elements: Pair,
	comparator: Comparator? = null,
) = TreeMap(comparator).also { it.putAll(elements.toMap()) }

/**
 * Converts this map to a tree map.
 */
fun , V> Map.toTreeMap() = TreeMap(this)

/**
 * Converts this map to a tree map with the specified [comparator].
 */
fun  Map.toTreeMap(comparator: Comparator) =
	TreeMap(comparator).also { it.putAll(this) }

/**
 * Creates a new empty [MutableMap] as [LinkedHashMap].
 */
inline fun  newMutableMap(): MutableMap = LinkedHashMap()

/**
 * Creates a new mutable map with the specified elements.
 */
inline fun  newMutableMap(vararg elements: Pair): MutableMap = mutableMapOf(*elements)

/**
 * Creates a new map with the specified elements.
 */
inline fun  newMap(vararg elements: Pair): Map = mapOf(*elements)

/**
 * Creates a new [ExpiringMap] with the specified builder.
 */
inline fun  newExpiringMap(builder: ExpiringMapBuilder): ExpiringMap = ExpiringMap
	.builder()
	.apply(builder.cast())
	.build()

/**
 * Converts this [Map] in to a [ExpiringMap] with the specified builder.
 */
inline fun  Map.toExpiringMap(builder: ExpiringMapBuilder): ExpiringMap =
	newExpiringMap(builder)
		.apply {
			putAll(this@toExpiringMap)
		}

/**
 * Reverses this map, this is, keys will be values and values will be keys.
 */
fun  Map.reverse(): Map {
	val result = LinkedHashMap()
	for ((key, value) in this)
		result[value] = key
	return result
}

/**
 * Reverses this mutable map, this is, keys will be values and values will be keys.
 */
@JvmName("mutableReverse")
fun  MutableMap.reverse(): MutableMap {
	val result = LinkedHashMap()
	for ((key, value) in this)
		result[value] = key
	return result
}

/**
 * Finds the first value occurrence by the given [predicate] or nulls if nothing is found.
 */
inline fun  Map.findValue(predicate: (V) -> Boolean): V? {
	for ((_, value) in this) {
		if (predicate(value))
			return value
	}
	return null
}

/**
 * Finds the last value occurrence by the given [predicate] or nulls if nothing is found.
 */
inline fun  Map.findLastValue(predicate: (V) -> Boolean): V? {
	var last: V? = null
	for ((_, value) in this) {
		if (predicate(value))
			last = value
	}
	return last
}

/**
 * Finds the first key occurrence by the given [predicate] or nulls if nothing is found.
 */
inline fun  Map.findKey(predicate: (K) -> Boolean): K? {
	for ((key, _) in this) {
		if (predicate(key))
			return key
	}
	return null
}

/**
 * Finds the last key occurrence by the given [predicate] or nulls if nothing is found.
 */
inline fun  Map.findLastKey(predicate: (K) -> Boolean): K? {
	var last: K? = null
	for ((key, _) in this) {
		if (predicate(key))
			last = key
	}
	return last
}

/**
 * Finds the first value occurrence by the given [predicate]
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.firstValue(predicate: (V) -> Boolean): V {
	for ((_, value) in this) {
		if (predicate(value))
			return value
	}
	noElementError("No value found with the given predicate.")
}

/**
 * Finds the last value occurrence by the given [predicate]
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastValue(predicate: (V) -> Boolean): V {
	var last: V? = null
	var found = false
	for ((_, value) in this) {
		if (predicate(value)) {
			last = value
			found = true
		}
	}
	if (!found) noElementError("No value found with the given predicate.")
	return last as V
}

/**
 * Finds the first value occurrence of the given [predicate] selecting by entries
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.firstValueBy(predicate: (Entry) -> Boolean): V {
	for (entry in this) {
		if (predicate(entry))
			return entry.value
	}
	noElementError("No value found with the given predicate.")
}

/**
 * Finds the last value occurrence of the given [predicate] selecting by entries
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastValueBy(predicate: (Entry) -> Boolean): V {
	var last: V? = null
	var found = false
	for (entry in this) {
		if (predicate(entry)) {
			last = entry.value
			found = true
		}
	}
	if (!found) noElementError("No value found with the given predicate.")
	return last as V
}

/**
 * Finds the first value occurrence of the given [predicate] selecting by keys
 * or throws a exception if nothing is found.
 */
inline fun  Map.firstValueByKey(predicate: (K) -> Boolean): V {
	for ((key, value) in this) {
		if (predicate(key))
			return value
	}
	noElementError("No value found with the given predicate.")
}

/**
 * Finds the last value occurrence of the given [predicate] selecting by keys
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastValueByKey(predicate: (K) -> Boolean): V {
	var last: V? = null
	var found = false
	for ((key, value) in this) {
		if (predicate(key)) {
			last = value
			found = true
		}
	}
	if (!found) noElementError("No value found with the given predicate.")
	return last as V
}

/**
 * Finds the first key occurrence of the given [predicate]
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.firstKey(predicate: (K) -> Boolean): K {
	for ((key, _) in this) {
		if (predicate(key))
			return key
	}
	noElementError("No key found with the given predicate.")
}

/**
 * Finds the last key occurrence of the given [predicate]
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastKey(predicate: (K) -> Boolean): K {
	for ((key, _) in this) {
		if (predicate(key))
			return key
	}
	noElementError("No key found with the given predicate.")
}

/**
 * Finds the first key occurrence of the given [predicate] selecting by entries
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.firstKeyBy(predicate: (Entry) -> Boolean): K {
	for (entry in this) {
		if (predicate(entry))
			return entry.key
	}
	noElementError("No key found with the given predicate.")
}

/**
 * Finds the last key occurrence of the given [predicate] selecting by entries
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastKeyBy(predicate: (Entry) -> Boolean): K {
	var last: K? = null
	var found = false
	for (entry in this) {
		if (predicate(entry)) {
			last = entry.key
			found = true
		}
	}
	if (!found) noElementError("No key found with the given predicate.")
	return last as K
}

/**
 * Finds the first key occurrence of the given [predicate] selecting by values
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.firstKeyByValue(predicate: (V) -> Boolean): K {
	for ((key, value) in this) {
		if (predicate(value))
			return key
	}
	noElementError("No key found with the given predicate.")
}

/**
 * Finds the last key occurrence of the given [predicate] selecting by values
 * or throws a [NoSuchElementException] if nothing is found.
 */
inline fun  Map.lastKeyByValue(predicate: (V) -> Boolean): K {
	var last: K? = null
	var found = false
	for ((key, value) in this) {
		if (predicate(value)) {
			last = key
			found = true
		}
	}
	if (!found) noElementError("No key found with the given predicate.")
	return last as K
}

/**
 * Performs the given [action] for each key of this map.
 */
inline fun  Map.forEachKey(action: (K) -> Unit) = keys.forEach(action)

/**
 * Performs the given [action] for each value of this map.
 */
inline fun  Map.forEachValue(action: (V) -> Unit) = values.forEach(action)

/**
 * Performs the given [action] for each key indexed of this map.
 */
inline fun  Map.forEachKeyIndexed(action: (Int, K) -> Unit) = keys.forEachIndexed(action)

/**
 * Performs the given [action] for each value indexed of this map.
 */
inline fun  Map.forEachValueIndexed(action: (Int, V) -> Unit) = values.forEachIndexed(action)

/**
 * Performs the given [action] on each key of this map.
 */
inline fun  Map.onEachKey(action: (K) -> Unit) = keys.onEach(action)

/**
 * Performs the given [action] on each value of this map.
 */
inline fun  Map.onEachValue(action: (V) -> Unit) = values.onEach(action)

/**
 * Performs the given [action] on each key indexed of this map.
 */
inline fun  Map.onEachKeyIndexed(action: (Int, K) -> Unit) = keys.onEachIndexed(action)

/**
 * Performs the given [action] on each value indexed of this map.
 */
inline fun  Map.onEachValueIndexed(action: (Int, V) -> Unit) = values.onEachIndexed(action)

/**
 * Create a sorted map of this map by natural comparator of [K].
 */
fun , V> Map.sorted() = TreeMap(this)

/**
 * Create a sorted map of this map by the comparator of the comparable [K] in descending order.
 */
fun , V> Map.sortedDescending() = toTreeMap(compareByDescending { it })

/**
 * Create a sorted map of this map by the given comparator comparing the keys of this map.
 */
fun  Map.sortedWith(comparator: Comparator) = toTreeMap(comparator)

/**
 * Create a sorted map of this map by the given comparator comparing the keys of this map.
 */
inline fun  Map.sortedBy(crossinline compare: (K) -> Boolean) =
	toTreeMap(compareBy(compare))

/**
 * Create a sorted map of this map by the given comparator comparing the keys of this map in desceding order.
 */
fun  Map.sortedWithDescending(comparator: Comparator) =
	toTreeMap(comparator.reversed())

/**
 * Create a sorted map of this map by the given comparator comparing the keys of this map in desceding order.
 */
inline fun  Map.sortedByDescending(crossinline compare: (K) -> Boolean) =
	toTreeMap(compareByDescending(compare))

/**
 * Sorts this map by the natural order of [V].
 * ### This not keeps the key sequence by the values.
 */
fun > Map.sortedValues() : Map {
	val result = newMutableMap()
	val sorted = values.sorted()
	for ((index, key) in keys.withIndex())
		result[key] = sorted[index]
	return result
}

/**
 * Sorts this map by the [valueComparator] comparing the values of this map.
 * ### This not keeps the key sequence by the values.
 */
fun  Map.sortedValuesWith(valueComparator: Comparator) : Map {
	val result = newMutableMap()
	val sorted = values.sortedWith(valueComparator)
	for ((index, key) in keys.withIndex())
		result[key] = sorted[index]
	return result
}

/**
 * Sorts this map by the [keyComparator] and [valueComparator].
 * ### This not keeps the key sequence by the values.
 */
fun  Map.sortedWith(
	keyComparator: Comparator,
	valueComparator: Comparator
) : Map {
	val result = newMutableMap()
	val keys = keys.sortedWith(keyComparator)
	val values = values.sortedWith(valueComparator)
	for (i in 0 until size)
		result[keys[i]] = values[i]
	return result
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy